v0.1.13 - Fix Kind 23458 test script: use websocat for bidirectional relay communication and correct nak decrypt flag (-p instead of --recipient-pubkey). Admin command system now fully functional end-to-end with NIP-44 encryption.
This commit is contained in:
535
docs/ADMIN_COMMANDS_PLAN.md
Normal file
535
docs/ADMIN_COMMANDS_PLAN.md
Normal file
@@ -0,0 +1,535 @@
|
||||
# Ginxsom Admin Commands Implementation Plan
|
||||
|
||||
## Overview
|
||||
|
||||
This document outlines the implementation plan for Ginxsom's admin command system, adapted from c-relay's event-based administration system. Commands are sent as NIP-44 encrypted Kind 23456 events and responses are returned as Kind 23457 events.
|
||||
|
||||
## Command Analysis: c-relay vs Ginxsom
|
||||
|
||||
### Commands to Implement (Blossom-Relevant)
|
||||
|
||||
| c-relay Command | Ginxsom Equivalent | Rationale |
|
||||
|-----------------|-------------------|-----------|
|
||||
| `config_query` | `config_query` | Query Blossom server configuration |
|
||||
| `config_update` | `config_update` | Update server settings dynamically |
|
||||
| `stats_query` | `stats_query` | Database statistics (blobs, storage, etc.) |
|
||||
| `system_status` | `system_status` | Server health and status |
|
||||
| `sql_query` | `sql_query` | Direct database queries for debugging |
|
||||
| N/A | `blob_list` | List blobs by pubkey or criteria |
|
||||
| N/A | `storage_stats` | Storage usage and capacity info |
|
||||
| N/A | `mirror_status` | Status of mirroring operations |
|
||||
| N/A | `report_query` | Query content reports (BUD-09) |
|
||||
|
||||
### Commands to Exclude (Not Blossom-Relevant)
|
||||
|
||||
| c-relay Command | Reason for Exclusion |
|
||||
|-----------------|---------------------|
|
||||
| `auth_add_blacklist` | Blossom uses different auth model (per-blob, not per-pubkey) |
|
||||
| `auth_add_whitelist` | Same as above |
|
||||
| `auth_delete_rule` | Same as above |
|
||||
| `auth_query_all` | Same as above |
|
||||
| `system_clear_auth` | Same as above |
|
||||
|
||||
**Note**: Blossom's authentication is event-based per operation (upload/delete), not relay-level whitelist/blacklist. Auth rules in Ginxsom are configured via the `auth_rules` table but managed differently than c-relay.
|
||||
|
||||
## Event Structure
|
||||
|
||||
### Admin Command Event (Kind 23456)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "event_id",
|
||||
"pubkey": "admin_public_key",
|
||||
"created_at": 1234567890,
|
||||
"kind": 23456,
|
||||
"content": "NIP44_ENCRYPTED_COMMAND_ARRAY",
|
||||
"tags": [
|
||||
["p", "blossom_server_pubkey"]
|
||||
],
|
||||
"sig": "event_signature"
|
||||
}
|
||||
```
|
||||
|
||||
### Admin Response Event (Kind 23457)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "response_event_id",
|
||||
"pubkey": "blossom_server_pubkey",
|
||||
"created_at": 1234567890,
|
||||
"kind": 23457,
|
||||
"content": "NIP44_ENCRYPTED_RESPONSE_OBJECT",
|
||||
"tags": [
|
||||
["p", "admin_public_key"],
|
||||
["e", "request_event_id"]
|
||||
],
|
||||
"sig": "response_event_signature"
|
||||
}
|
||||
```
|
||||
|
||||
## Command Specifications
|
||||
|
||||
### 1. Configuration Management
|
||||
|
||||
#### `config_query`
|
||||
|
||||
Query server configuration parameters.
|
||||
|
||||
**Command Format:**
|
||||
```json
|
||||
["config_query", "all"]
|
||||
["config_query", "category", "blossom"]
|
||||
["config_query", "key", "max_file_size"]
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"query_type": "config_all",
|
||||
"total_results": 15,
|
||||
"timestamp": 1234567890,
|
||||
"data": [
|
||||
{
|
||||
"key": "max_file_size",
|
||||
"value": "104857600",
|
||||
"data_type": "integer",
|
||||
"category": "blossom",
|
||||
"description": "Maximum file size in bytes"
|
||||
},
|
||||
{
|
||||
"key": "enable_relay_connect",
|
||||
"value": "true",
|
||||
"data_type": "boolean",
|
||||
"category": "relay",
|
||||
"description": "Enable relay client functionality"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Configuration Categories:**
|
||||
- `blossom`: Blossom protocol settings (max_file_size, storage_path, etc.)
|
||||
- `relay`: Relay client settings (enable_relay_connect, kind_0_content, etc.)
|
||||
- `auth`: Authentication settings (auth_enabled, nip42_required, etc.)
|
||||
- `limits`: Rate limits and quotas
|
||||
- `system`: System-level settings
|
||||
|
||||
#### `config_update`
|
||||
|
||||
Update configuration parameters dynamically.
|
||||
|
||||
**Command Format:**
|
||||
```json
|
||||
["config_update", [
|
||||
{
|
||||
"key": "max_file_size",
|
||||
"value": "209715200",
|
||||
"data_type": "integer",
|
||||
"category": "blossom"
|
||||
},
|
||||
{
|
||||
"key": "enable_relay_connect",
|
||||
"value": "true",
|
||||
"data_type": "boolean",
|
||||
"category": "relay"
|
||||
}
|
||||
]]
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"query_type": "config_update",
|
||||
"status": "success",
|
||||
"total_results": 2,
|
||||
"timestamp": 1234567890,
|
||||
"data": [
|
||||
{
|
||||
"key": "max_file_size",
|
||||
"value": "209715200",
|
||||
"status": "updated",
|
||||
"restart_required": false
|
||||
},
|
||||
{
|
||||
"key": "enable_relay_connect",
|
||||
"value": "true",
|
||||
"status": "updated",
|
||||
"restart_required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Statistics and Monitoring
|
||||
|
||||
#### `stats_query`
|
||||
|
||||
Get comprehensive database and storage statistics.
|
||||
|
||||
**Command Format:**
|
||||
```json
|
||||
["stats_query"]
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"query_type": "stats_query",
|
||||
"timestamp": 1234567890,
|
||||
"database_size_bytes": 1048576,
|
||||
"storage_size_bytes": 10737418240,
|
||||
"total_blobs": 1543,
|
||||
"unique_uploaders": 234,
|
||||
"blob_types": [
|
||||
{"type": "image/jpeg", "count": 856, "size_bytes": 5368709120, "percentage": 55.4},
|
||||
{"type": "image/png", "count": 432, "size_bytes": 3221225472, "percentage": 28.0},
|
||||
{"type": "video/mp4", "count": 123, "size_bytes": 2147483648, "percentage": 8.0}
|
||||
],
|
||||
"time_stats": {
|
||||
"total": 1543,
|
||||
"last_24h": 45,
|
||||
"last_7d": 234,
|
||||
"last_30d": 876
|
||||
},
|
||||
"top_uploaders": [
|
||||
{"pubkey": "abc123...", "blob_count": 234, "total_bytes": 1073741824, "percentage": 15.2},
|
||||
{"pubkey": "def456...", "blob_count": 187, "total_bytes": 858993459, "percentage": 12.1}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `system_status`
|
||||
|
||||
Get current system status and health metrics.
|
||||
|
||||
**Command Format:**
|
||||
```json
|
||||
["system_command", "system_status"]
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"query_type": "system_status",
|
||||
"timestamp": 1234567890,
|
||||
"uptime_seconds": 86400,
|
||||
"version": "0.1.0",
|
||||
"relay_client": {
|
||||
"enabled": true,
|
||||
"connected_relays": 1,
|
||||
"relay_status": [
|
||||
{
|
||||
"url": "wss://relay.laantungir.net",
|
||||
"state": "connected",
|
||||
"events_received": 12,
|
||||
"events_published": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
"storage": {
|
||||
"path": "/home/teknari/lt_gitea/ginxsom/blobs",
|
||||
"total_bytes": 10737418240,
|
||||
"available_bytes": 53687091200,
|
||||
"usage_percentage": 16.7
|
||||
},
|
||||
"database": {
|
||||
"path": "db/52e366edfa4e9cc6a6d4653828e51ccf828a2f5a05227d7a768f33b5a198681a.db",
|
||||
"size_bytes": 1048576,
|
||||
"total_blobs": 1543
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Blossom-Specific Commands
|
||||
|
||||
#### `blob_list`
|
||||
|
||||
List blobs with filtering options.
|
||||
|
||||
**Command Format:**
|
||||
```json
|
||||
["blob_list", "all"]
|
||||
["blob_list", "pubkey", "abc123..."]
|
||||
["blob_list", "type", "image/jpeg"]
|
||||
["blob_list", "recent", 50]
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"query_type": "blob_list",
|
||||
"total_results": 50,
|
||||
"timestamp": 1234567890,
|
||||
"data": [
|
||||
{
|
||||
"sha256": "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553",
|
||||
"size": 184292,
|
||||
"type": "application/pdf",
|
||||
"uploaded_at": 1725105921,
|
||||
"uploader_pubkey": "abc123...",
|
||||
"url": "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `storage_stats`
|
||||
|
||||
Get detailed storage statistics.
|
||||
|
||||
**Command Format:**
|
||||
```json
|
||||
["storage_stats"]
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"query_type": "storage_stats",
|
||||
"timestamp": 1234567890,
|
||||
"storage_path": "/home/teknari/lt_gitea/ginxsom/blobs",
|
||||
"total_bytes": 10737418240,
|
||||
"available_bytes": 53687091200,
|
||||
"used_bytes": 10737418240,
|
||||
"usage_percentage": 16.7,
|
||||
"blob_count": 1543,
|
||||
"average_blob_size": 6958592,
|
||||
"largest_blob": {
|
||||
"sha256": "abc123...",
|
||||
"size": 104857600,
|
||||
"type": "video/mp4"
|
||||
},
|
||||
"by_type": [
|
||||
{"type": "image/jpeg", "count": 856, "total_bytes": 5368709120},
|
||||
{"type": "image/png", "count": 432, "total_bytes": 3221225472}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `mirror_status`
|
||||
|
||||
Get status of blob mirroring operations (BUD-04).
|
||||
|
||||
**Command Format:**
|
||||
```json
|
||||
["mirror_status"]
|
||||
["mirror_status", "sha256", "abc123..."]
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"query_type": "mirror_status",
|
||||
"timestamp": 1234567890,
|
||||
"total_mirrors": 23,
|
||||
"data": [
|
||||
{
|
||||
"sha256": "abc123...",
|
||||
"source_url": "https://cdn.example.com/abc123.jpg",
|
||||
"status": "completed",
|
||||
"mirrored_at": 1725105921,
|
||||
"size": 1048576
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `report_query`
|
||||
|
||||
Query content reports (BUD-09).
|
||||
|
||||
**Command Format:**
|
||||
```json
|
||||
["report_query", "all"]
|
||||
["report_query", "blob", "abc123..."]
|
||||
["report_query", "type", "nudity"]
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"query_type": "report_query",
|
||||
"total_results": 12,
|
||||
"timestamp": 1234567890,
|
||||
"data": [
|
||||
{
|
||||
"report_id": 1,
|
||||
"blob_sha256": "abc123...",
|
||||
"report_type": "nudity",
|
||||
"reporter_pubkey": "def456...",
|
||||
"content": "Inappropriate content",
|
||||
"reported_at": 1725105921
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Database Queries
|
||||
|
||||
#### `sql_query`
|
||||
|
||||
Execute read-only SQL queries for debugging.
|
||||
|
||||
**Command Format:**
|
||||
```json
|
||||
["sql_query", "SELECT * FROM blobs LIMIT 10"]
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"query_type": "sql_query",
|
||||
"request_id": "request_event_id",
|
||||
"timestamp": 1234567890,
|
||||
"query": "SELECT * FROM blobs LIMIT 10",
|
||||
"execution_time_ms": 12,
|
||||
"row_count": 10,
|
||||
"columns": ["sha256", "size", "type", "uploaded_at", "uploader_pubkey"],
|
||||
"rows": [
|
||||
["b1674191...", 184292, "application/pdf", 1725105921, "abc123..."]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Security:**
|
||||
- Only SELECT statements allowed
|
||||
- Query timeout: 5 seconds
|
||||
- Result row limit: 1000 rows
|
||||
- All queries logged
|
||||
|
||||
## Implementation Architecture
|
||||
|
||||
### 1. Command Processing Flow
|
||||
|
||||
```
|
||||
1. Relay client receives Kind 23456 event
|
||||
2. Verify sender is admin_pubkey
|
||||
3. Decrypt content using NIP-44
|
||||
4. Parse command array
|
||||
5. Validate command structure
|
||||
6. Execute command handler
|
||||
7. Generate response object
|
||||
8. Encrypt response using NIP-44
|
||||
9. Create Kind 23457 event
|
||||
10. Publish to relays
|
||||
```
|
||||
|
||||
### 2. Code Structure
|
||||
|
||||
**New Files:**
|
||||
- `src/admin_commands.c` - Command handlers
|
||||
- `src/admin_commands.h` - Command interface
|
||||
- `src/nip44.c` - NIP-44 encryption wrapper (uses nostr_core_lib)
|
||||
- `src/nip44.h` - NIP-44 interface
|
||||
|
||||
**Modified Files:**
|
||||
- `src/relay_client.c` - Add command processing to `on_admin_command_event()`
|
||||
- `src/main.c` - Initialize admin command system
|
||||
|
||||
### 3. Database Schema Additions
|
||||
|
||||
```sql
|
||||
-- Admin command log
|
||||
CREATE TABLE IF NOT EXISTS admin_commands (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
event_id TEXT NOT NULL,
|
||||
command_type TEXT NOT NULL,
|
||||
admin_pubkey TEXT NOT NULL,
|
||||
executed_at INTEGER NOT NULL,
|
||||
execution_time_ms INTEGER,
|
||||
status TEXT NOT NULL,
|
||||
error TEXT
|
||||
);
|
||||
|
||||
-- Create index for command history queries
|
||||
CREATE INDEX IF NOT EXISTS idx_admin_commands_executed
|
||||
ON admin_commands(executed_at DESC);
|
||||
```
|
||||
|
||||
### 4. Configuration Keys
|
||||
|
||||
**Blossom Category:**
|
||||
- `max_file_size` - Maximum upload size in bytes
|
||||
- `storage_path` - Blob storage directory
|
||||
- `cdn_origin` - CDN URL for blob descriptors
|
||||
- `enable_nip94` - Include NIP-94 tags in responses
|
||||
|
||||
**Relay Category:**
|
||||
- `enable_relay_connect` - Enable relay client
|
||||
- `kind_0_content` - Profile metadata JSON
|
||||
- `kind_10002_tags` - Relay list JSON array
|
||||
|
||||
**Auth Category:**
|
||||
- `auth_enabled` - Enable auth rules system
|
||||
- `require_auth_upload` - Require auth for uploads
|
||||
- `require_auth_delete` - Require auth for deletes
|
||||
|
||||
**Limits Category:**
|
||||
- `max_blobs_per_user` - Per-user blob limit
|
||||
- `rate_limit_uploads` - Uploads per minute
|
||||
- `max_total_storage` - Total storage limit in bytes
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: NIP-44 Encryption Support
|
||||
- Integrate nostr_core_lib NIP-44 functions
|
||||
- Create encryption/decryption wrappers
|
||||
- Test with sample data
|
||||
|
||||
### Phase 2: Command Infrastructure
|
||||
- Create admin_commands.c/h
|
||||
- Implement command parser
|
||||
- Add command logging to database
|
||||
- Implement response builder
|
||||
|
||||
### Phase 3: Core Commands
|
||||
- Implement `config_query`
|
||||
- Implement `config_update`
|
||||
- Implement `stats_query`
|
||||
- Implement `system_status`
|
||||
|
||||
### Phase 4: Blossom Commands
|
||||
- Implement `blob_list`
|
||||
- Implement `storage_stats`
|
||||
- Implement `mirror_status`
|
||||
- Implement `report_query`
|
||||
|
||||
### Phase 5: Advanced Features
|
||||
- Implement `sql_query` with security
|
||||
- Add command history tracking
|
||||
- Implement rate limiting for admin commands
|
||||
|
||||
### Phase 6: Testing & Documentation
|
||||
- Create test suite for each command
|
||||
- Update README.md with admin API section
|
||||
- Create example scripts using nak tool
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Authentication**: Only admin_pubkey can send commands
|
||||
2. **Encryption**: All commands/responses use NIP-44
|
||||
3. **Logging**: All admin actions logged to database
|
||||
4. **Rate Limiting**: Prevent admin command flooding
|
||||
5. **SQL Safety**: Only SELECT allowed, with timeout and row limits
|
||||
6. **Input Validation**: Strict validation of all command parameters
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
1. **Unit Tests**: Test each command handler independently
|
||||
2. **Integration Tests**: Test full command flow with encryption
|
||||
3. **Security Tests**: Verify auth checks and SQL injection prevention
|
||||
4. **Performance Tests**: Ensure commands don't block relay operations
|
||||
5. **Manual Tests**: Use nak tool to send real encrypted commands
|
||||
|
||||
## Documentation Updates
|
||||
|
||||
Add new section to README.md after "Content Reporting (BUD-09)":
|
||||
|
||||
```markdown
|
||||
## Administrator API
|
||||
|
||||
Ginxsom uses an event-based administration system where commands are sent as
|
||||
NIP-44 encrypted Kind 23456 events and responses are returned as Kind 23457
|
||||
events. This provides secure, cryptographically authenticated remote management.
|
||||
|
||||
[Full admin API documentation here]
|
||||
Reference in New Issue
Block a user