Files
NxMesh-old/docs/api.md
GW_MC 43b2e44d95 Add project structure and roadmap documentation
- Created `project-structure.md` to outline the directory layout, crate dependencies, design principles, module guidelines, and naming conventions for the NxMesh codebase.
- Introduced `roadmap.md` detailing the development phases, milestones, tasks, deliverables, and resource requirements for the NxMesh project, spanning from foundational setup to enterprise features.
2026-03-03 04:13:31 +00:00

1108 lines
20 KiB
Markdown

# NxMesh API Specification
## Overview
This document outlines the API structure for NxMesh. The system exposes:
- **REST API** for external integrations and Web UI
- **gRPC API** for master-agent communication
- **WebSocket API** for real-time events
---
## REST API
### Base Information
| Property | Value |
|----------|-------|
| Base URL | `https://api.nxmesh.io/v1` |
| Content-Type | `application/json` |
| Authentication | Bearer Token (JWT) |
| Rate Limit | 1000 requests/minute |
### Authentication
#### Login
```http
POST /auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "secure_password"
}
```
Response:
```json
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
"expires_in": 3600,
"token_type": "Bearer"
}
```
#### Refresh Token
```http
POST /auth/refresh
Content-Type: application/json
{
"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4..."
}
```
---
### Organizations
#### List Organizations
```http
GET /organizations?page=1&per_page=20
Authorization: Bearer {token}
```
Response:
```json
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Acme Corp",
"slug": "acme-corp",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 1
}
}
```
#### Create Organization
```http
POST /organizations
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "Acme Corp",
"slug": "acme-corp"
}
```
#### Get Organization
```http
GET /organizations/{organization_id}
Authorization: Bearer {token}
```
#### Update Organization
```http
PATCH /organizations/{organization_id}
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "Acme Corporation"
}
```
#### Delete Organization
```http
DELETE /organizations/{organization_id}
Authorization: Bearer {token}
```
---
### Workspaces
#### List Workspaces
```http
GET /organizations/{organization_id}/workspaces?page=1&per_page=20
Authorization: Bearer {token}
```
Response:
```json
{
"data": [
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"organization_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Production",
"slug": "production",
"created_at": "2026-01-15T10:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 3
}
}
```
#### Create Workspace
```http
POST /organizations/{organization_id}/workspaces
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "Staging",
"slug": "staging"
}
```
#### Get Workspace
```http
GET /workspaces/{workspace_id}
Authorization: Bearer {token}
```
#### Update Workspace
```http
PATCH /workspaces/{workspace_id}
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "Staging Environment"
}
```
#### Delete Workspace
```http
DELETE /workspaces/{workspace_id}
Authorization: Bearer {token}
```
---
### Agents
#### List Agents
```http
GET /workspaces/{workspace_id}/agents?page=1&per_page=20&state=online
Authorization: Bearer {token}
```
Query Parameters:
- `state` - Filter by state: `online`, `offline`, `degraded`, `all`
- `label_selector` - Filter by labels: `env=production,region=us-east`
Response:
```json
{
"data": [
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"workspace_id": "660e8400-e29b-41d4-a716-446655440001",
"name": "web-server-01",
"hostname": "web-01.internal",
"ip_address": "10.0.1.10",
"version": "0.1.0",
"state": "online",
"deployment_mode": "docker_sidecar",
"last_seen_at": "2026-03-02T12:00:00Z",
"capabilities": ["http2", "websocket"],
"labels": {
"env": "production",
"region": "us-east-1"
},
"created_at": "2026-02-01T10:00:00Z"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 5
}
}
```
#### Get Agent
```http
GET /agents/{agent_id}
Authorization: Bearer {token}
```
Response includes health details:
```json
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"workspace_id": "660e8400-e29b-41d4-a716-446655440001",
"name": "web-server-01",
"hostname": "web-01.internal",
"ip_address": "10.0.1.10",
"version": "0.1.0",
"state": "online",
"deployment_mode": "docker_sidecar",
"last_seen_at": "2026-03-02T12:00:00Z",
"capabilities": ["http2", "websocket"],
"labels": {
"env": "production",
"region": "us-east-1"
},
"health": {
"nginx_status": "running",
"nginx_uptime_seconds": 86400,
"active_connections": 42,
"requests_per_second": 150.5,
"cpu_percent": 25.0,
"memory_used_mb": 512,
"config_version": 42
},
"created_at": "2026-02-01T10:00:00Z"
}
```
#### Create Agent Registration Token
```http
POST /workspaces/{workspace_id}/agents/tokens
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "web-server-02",
"labels": {
"env": "production",
"region": "us-west-1"
},
"expires_in_hours": 24
}
```
Response:
```json
{
"token": "nxmesh_agent_eyJhZ2VudF9pZCI6ICI3NzBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDMi...",
"agent_id": "770e8400-e29b-41d4-a716-446655440003",
"expires_at": "2026-03-03T12:00:00Z"
}
```
#### Update Agent
```http
PATCH /agents/{agent_id}
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "web-server-01-renamed",
"labels": {
"env": "production",
"region": "us-east-1",
"tier": "web"
}
}
```
#### Delete Agent
```http
DELETE /agents/{agent_id}
Authorization: Bearer {token}
```
#### Reload Agent Nginx
```http
POST /agents/{agent_id}/reload
Authorization: Bearer {token}
```
Response:
```json
{
"success": true,
"message": "Nginx reloaded successfully",
"timestamp": "2026-03-02T12:05:00Z"
}
```
---
### Virtual Hosts
#### List Virtual Hosts
```http
GET /workspaces/{workspace_id}/virtual-hosts?page=1&per_page=20
Authorization: Bearer {token}
```
Response:
```json
{
"data": [
{
"id": "880e8400-e29b-41d4-a716-446655440004",
"workspace_id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Main Website",
"server_name": "example.com www.example.com",
"listen_port": 443,
"ssl_enabled": true,
"ssl_certificate_id": "990e8400-e29b-41d4-a716-446655440005",
"http2_enabled": true,
"target_agents": {
"type": "all"
},
"created_at": "2026-02-01T10:00:00Z",
"updated_at": "2026-02-15T14:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 10
}
}
```
#### Create Virtual Host
```http
POST /workspaces/{workspace_id}/virtual-hosts
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "API Gateway",
"server_name": "api.example.com",
"listen_port": 443,
"ssl_enabled": true,
"ssl_certificate_id": "990e8400-e29b-41d4-a716-446655440005",
"http2_enabled": true,
"locations": [
{
"path": "/api/v1",
"upstream_id": "aa0e8400-e29b-41d4-a716-446655440006",
"custom_headers": [
{
"name": "X-Forwarded-Proto",
"value": "$scheme"
}
]
},
{
"path": "/health",
"proxy_pass": "http://localhost:8080/health"
}
],
"target_agents": {
"type": "selector",
"label_selector": "env=production"
}
}
```
#### Get Virtual Host
```http
GET /virtual-hosts/{virtual_host_id}
Authorization: Bearer {token}
```
#### Update Virtual Host
```http
PATCH /virtual-hosts/{virtual_host_id}
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "API Gateway v2",
"locations": [
{
"path": "/api/v2",
"upstream_id": "aa0e8400-e29b-41d4-a716-446655440007"
}
]
}
```
#### Delete Virtual Host
```http
DELETE /virtual-hosts/{virtual_host_id}
Authorization: Bearer {token}
```
---
### Upstreams
#### List Upstreams
```http
GET /workspaces/{workspace_id}/upstreams?page=1&per_page=20
Authorization: Bearer {token}
```
Response:
```json
{
"data": [
{
"id": "aa0e8400-e29b-41d4-a716-446655440006",
"workspace_id": "660e8400-e29b-41d4-a716-446655440001",
"name": "api-backend",
"algorithm": "round_robin",
"servers": [
{
"address": "10.0.1.20:8080",
"weight": 1,
"backup": false,
"max_fails": 3,
"fail_timeout": 30
},
{
"address": "10.0.1.21:8080",
"weight": 1,
"backup": false,
"max_fails": 3,
"fail_timeout": 30
}
],
"health_check": {
"enabled": true,
"path": "/health",
"interval": 10,
"timeout": 5
},
"created_at": "2026-02-01T10:00:00Z",
"updated_at": "2026-02-15T14:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 5
}
}
```
#### Create Upstream
```http
POST /workspaces/{workspace_id}/upstreams
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "web-backend",
"algorithm": "least_connections",
"servers": [
{
"address": "10.0.1.30:8080",
"weight": 2,
"backup": false
},
{
"address": "10.0.1.31:8080",
"weight": 1,
"backup": false
},
{
"address": "10.0.1.32:8080",
"weight": 1,
"backup": true
}
],
"health_check": {
"enabled": true,
"path": "/health",
"interval": 10,
"timeout": 5
}
}
```
#### Get Upstream
```http
GET /upstreams/{upstream_id}
Authorization: Bearer {token}
```
#### Update Upstream
```http
PATCH /upstreams/{upstream_id}
Authorization: Bearer {token}
Content-Type: application/json
{
"servers": [
{
"address": "10.0.1.30:8080",
"weight": 3,
"backup": false
}
]
}
```
#### Delete Upstream
```http
DELETE /upstreams/{upstream_id}
Authorization: Bearer {token}
```
---
### Certificates
#### List Certificates
```http
GET /workspaces/{workspace_id}/certificates?page=1&per_page=20
Authorization: Bearer {token}
```
Response:
```json
{
"data": [
{
"id": "990e8400-e29b-41d4-a716-446655440005",
"workspace_id": "660e8400-e29b-41d4-a716-446655440001",
"domain": "example.com",
"is_wildcard": false,
"provider": "letsencrypt",
"status": "active",
"issued_at": "2026-02-01T10:00:00Z",
"expires_at": "2026-05-01T10:00:00Z",
"auto_renew": true,
"created_at": "2026-02-01T10:00:00Z"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 3
}
}
```
#### Request Certificate
```http
POST /workspaces/{workspace_id}/certificates
Authorization: Bearer {token}
Content-Type: application/json
{
"domain": "api.example.com",
"provider": "letsencrypt",
"auto_renew": true
}
```
#### Get Certificate
```http
GET /certificates/{certificate_id}
Authorization: Bearer {token}
```
#### Delete Certificate
```http
DELETE /certificates/{certificate_id}
Authorization: Bearer {token}
```
---
### Metrics
#### Get Workspace Metrics
```http
GET /workspaces/{workspace_id}/metrics?from=2026-03-01T00:00:00Z&to=2026-03-02T00:00:00Z
Authorization: Bearer {token}
```
Response:
```json
{
"requests_total": 1234567,
"requests_per_second": 150.5,
"error_rate": 0.001,
"active_connections": 42,
"bandwidth": {
"in_bytes": 1073741824,
"out_bytes": 5368709120
},
"status_codes": {
"2xx": 1230000,
"3xx": 4000,
"4xx": 500,
"5xx": 67
}
}
```
#### Get Agent Metrics
```http
GET /agents/{agent_id}/metrics?from=2026-03-01T00:00:00Z&to=2026-03-02T00:00:00Z
Authorization: Bearer {token}
```
---
### Access Logs
#### Query Access Logs
```http
GET /workspaces/{workspace_id}/access-logs?from=2026-03-01T00:00:00Z&to=2026-03-02T00:00:00Z&status_code=500&limit=100
Authorization: Bearer {token}
```
Response:
```json
{
"data": [
{
"id": "bb0e8400-e29b-41d4-a716-446655440008",
"agent_id": "770e8400-e29b-41d4-a716-446655440002",
"timestamp": "2026-03-02T10:30:00Z",
"remote_addr": "192.168.1.100",
"method": "GET",
"uri": "/api/error",
"protocol": "HTTP/1.1",
"host": "api.example.com",
"status": 500,
"body_bytes_sent": 123,
"response_time_ms": 150.5,
"user_agent": "Mozilla/5.0...",
"referer": "https://example.com/",
"request_id": "req-123-456"
}
],
"meta": {
"total": 67,
"limit": 100
}
}
```
---
## Error Responses
All errors follow this format:
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"request_id": "req-abc-123",
"details": [
{
"field": "server_name",
"message": "Invalid domain format",
"code": "INVALID_FORMAT"
}
]
}
}
```
### Error Codes
| Code | HTTP Status | Description |
|------|-------------|-------------|
| `UNAUTHORIZED` | 401 | Authentication required or invalid credentials |
| `FORBIDDEN` | 403 | Insufficient permissions |
| `NOT_FOUND` | 404 | Resource not found |
| `VALIDATION_ERROR` | 422 | Request validation failed |
| `CONFLICT` | 409 | Resource conflict (e.g., duplicate slug) |
| `RATE_LIMITED` | 429 | Too many requests |
| `INTERNAL_ERROR` | 500 | Server internal error |
| `SERVICE_UNAVAILABLE` | 503 | Service temporarily unavailable |
---
## gRPC API (Master-Agent)
### Service Definition
```protobuf
syntax = "proto3";
package nxmesh.agent.v1;
option go_package = "github.com/nxmesh/api/agent/v1";
// AgentService defines the bidirectional communication between master and agents
service AgentService {
// Stream establishes a persistent connection for real-time communication
rpc Stream(stream AgentMessage) returns (stream MasterMessage);
// ReportHealth sends a health report to the master
rpc ReportHealth(HealthReport) returns (Ack);
// ReportMetrics sends metrics batch to the master
rpc ReportMetrics(MetricsBatch) returns (Ack);
}
// Messages sent from agent to master
message AgentMessage {
string agent_id = 1;
int64 timestamp = 2;
oneof payload {
RegistrationRequest registration = 3;
HealthReport health = 4;
ConfigStatus config_status = 5;
MetricsBatch metrics = 6;
LogBatch logs = 7;
Event event = 8;
}
}
// Messages sent from master to agent
message MasterMessage {
int64 timestamp = 1;
oneof payload {
RegistrationResponse registration_response = 2;
ConfigUpdate config_update = 3;
Command command = 4;
Ack ack = 5;
Error error = 6;
}
}
// Registration
message RegistrationRequest {
string token = 1;
string hostname = 2;
string ip_address = 3;
string version = 4;
repeated string capabilities = 5;
map<string, string> labels = 6;
DeploymentMode deployment_mode = 7;
}
message RegistrationResponse {
string agent_id = 1;
bool success = 2;
string error_message = 3;
int64 heartbeat_interval_seconds = 4;
}
enum DeploymentMode {
DEPLOYMENT_MODE_UNSPECIFIED = 0;
DOCKER_SIDECAR = 1;
KUBERNETES_SIDECAR = 2;
STANDALONE = 3;
}
// Health Reporting
message HealthReport {
NginxStatus nginx = 1;
SystemMetrics system = 2;
string config_checksum = 3;
int64 config_version = 4;
repeated Alert alerts = 5;
}
message NginxStatus {
bool is_running = 1;
uint32 pid = 2;
uint64 uptime_seconds = 3;
uint32 active_connections = 4;
uint64 total_requests = 5;
float requests_per_second = 6;
}
message SystemMetrics {
float cpu_percent = 1;
uint64 memory_used_bytes = 2;
uint64 memory_total_bytes = 3;
uint64 disk_used_bytes = 4;
uint64 disk_total_bytes = 5;
float load_average_1m = 6;
}
message Alert {
string id = 1;
string severity = 2; // info, warning, error, critical
string message = 3;
int64 timestamp = 4;
}
// Configuration
message ConfigUpdate {
string config_id = 1;
int64 version = 2;
repeated VirtualHost virtual_hosts = 3;
repeated Upstream upstreams = 4;
map<string, Certificate> certificates = 5;
GlobalSettings global_settings = 6;
}
message VirtualHost {
string id = 1;
string name = 2;
string server_name = 3;
uint32 listen_port = 4;
bool ssl_enabled = 5;
string ssl_certificate_id = 6;
bool http2_enabled = 7;
bool http3_enabled = 8;
repeated Location locations = 9;
map<string, string> custom_directives = 10;
}
message Location {
string path = 1;
string proxy_pass = 2;
string upstream_id = 3;
string root = 4;
string index = 5;
repeated Header custom_headers = 6;
repeated RewriteRule rewrite_rules = 7;
map<string, string> custom_directives = 8;
}
message Header {
string name = 1;
string value = 2;
bool always = 3;
}
message RewriteRule {
string pattern = 1;
string replacement = 2;
string flag = 3;
}
message Upstream {
string id = 1;
string name = 2;
LoadBalanceAlgorithm algorithm = 3;
repeated UpstreamServer servers = 4;
HealthCheckConfig health_check = 5;
uint32 keepalive_connections = 6;
}
enum LoadBalanceAlgorithm {
LOAD_BALANCE_ALGORITHM_UNSPECIFIED = 0;
ROUND_ROBIN = 1;
LEAST_CONNECTIONS = 2;
IP_HASH = 3;
WEIGHTED_ROUND_ROBIN = 4;
}
message UpstreamServer {
string address = 1;
uint32 weight = 2;
bool backup = 3;
bool down = 4;
uint32 max_fails = 5;
uint32 fail_timeout_seconds = 6;
}
message HealthCheckConfig {
bool enabled = 1;
string path = 2;
uint32 interval_seconds = 3;
uint32 timeout_seconds = 4;
uint32 healthy_threshold = 5;
uint32 unhealthy_threshold = 6;
}
message Certificate {
string id = 1;
string domain = 2;
string certificate_pem = 3;
string private_key_pem = 4;
int64 expires_at = 5;
}
message GlobalSettings {
map<string, string> nginx_directives = 1;
map<string, string> env_vars = 2;
}
message ConfigStatus {
string config_id = 1;
int64 version = 2;
ConfigApplyStatus status = 3;
string error_message = 4;
int64 applied_at = 5;
}
enum ConfigApplyStatus {
CONFIG_APPLY_STATUS_UNSPECIFIED = 0;
PENDING = 1;
VALIDATING = 2;
APPLYING = 3;
SUCCESS = 4;
FAILED = 5;
ROLLED_BACK = 6;
}
// Metrics
message MetricsBatch {
int64 timestamp = 1;
repeated Metric metrics = 2;
}
message Metric {
string name = 1;
double value = 2;
int64 timestamp = 3;
map<string, string> labels = 4;
MetricType type = 5;
}
enum MetricType {
METRIC_TYPE_UNSPECIFIED = 0;
GAUGE = 1;
COUNTER = 2;
HISTOGRAM = 3;
}
// Logs
message LogBatch {
repeated LogEntry entries = 1;
}
message LogEntry {
int64 timestamp = 1;
string level = 2;
string message = 3;
map<string, string> fields = 4;
}
// Commands
message Command {
string command_id = 1;
oneof command {
ReloadCommand reload = 2;
RestartCommand restart = 3;
StopCommand stop = 4;
GetStatusCommand get_status = 5;
ValidateConfigCommand validate_config = 6;
}
}
message ReloadCommand {
bool graceful = 1;
}
message RestartCommand {
bool force = 1;
}
message StopCommand {
bool graceful = 1;
uint32 timeout_seconds = 2;
}
message GetStatusCommand {}
message ValidateConfigCommand {
string config_content = 1;
}
// Events
message Event {
string event_id = 1;
string event_type = 2;
int64 timestamp = 3;
map<string, string> data = 4;
}
// Common messages
message Ack {
string message_id = 1;
bool success = 2;
string error_message = 3;
}
message Error {
string code = 1;
string message = 2;
map<string, string> details = 3;
}
```
---
## WebSocket API
### Connection
Connect to WebSocket endpoint with JWT token:
```javascript
const ws = new WebSocket('wss://api.nxmesh.io/v1/events?token={jwt_token}');
```
### Event Types
#### Agent Connected
```json
{
"type": "agent.connected",
"timestamp": "2026-03-02T12:00:00Z",
"data": {
"agent_id": "770e8400-e29b-41d4-a716-446655440002",
"hostname": "web-01.internal",
"ip_address": "10.0.1.10"
}
}
```
#### Agent Disconnected
```json
{
"type": "agent.disconnected",
"timestamp": "2026-03-02T12:05:00Z",
"data": {
"agent_id": "770e8400-e29b-41d4-a716-446655440002",
"reason": "connection_timeout"
}
}
```
#### Config Applied
```json
{
"type": "config.applied",
"timestamp": "2026-03-02T12:10:00Z",
"data": {
"agent_id": "770e8400-e29b-41d4-a716-446655440002",
"config_id": "config-123",
"version": 42,
"duration_ms": 150,
"success": true
}
}
```
#### Health Alert
```json
{
"type": "health.alert",
"timestamp": "2026-03-02T12:15:00Z",
"data": {
"agent_id": "770e8400-e29b-41d4-a716-446655440002",
"alert_id": "alert-456",
"severity": "warning",
"message": "High CPU usage: 85%",
"metric": "cpu_percent",
"value": 85.0
}
}
```
### Subscribing to Events
Clients can subscribe to specific event types:
```json
{
"action": "subscribe",
"events": ["agent.*", "config.*"],
"filter": {
"workspace_id": "660e8400-e29b-41d4-a716-446655440001"
}
}
```