# PhotonCloud REST API Guide **Version:** 1.0 **Last Updated:** 2025-12-12 **Target:** MVP-Alpha Phase ## Overview PhotonCloud provides REST/HTTP APIs for all core services, enabling easy access via `curl` for: - 組み込み環境 (Embedded environments) - Shell scripts and automation - Debugging and troubleshooting - Environments without gRPC tooling All REST APIs follow consistent patterns and run alongside gRPC services on dedicated HTTP ports. ## Service Port Map | Service | HTTP Port | gRPC Port | Purpose | |---------|-----------|-----------|---------| | **ChainFire** | 8081 | 50051 | Distributed KV store with Raft consensus | | **FlareDB** | 8082 | 50052 | SQL database (KV backend) | | **IAM** | 8083 | 50051 | Identity & Access Management | | **PlasmaVMC** | 8084 | 50051 | Virtual Machine Controller | | **k8shost** | 8085 | 6443 | Kubernetes Host (kubelet replacement) | | **CreditService** | 8086 | 50057 | Credit/Quota Management | | **PrismNET** | 8087 | 9090 | Network Management (VPC/Subnet) | | **NightLight** | 9090 | — | Prometheus TSDB (HTTP-only) | | **LightningSTOR** | 9000 | — | S3-compatible Object Storage | ## Common Patterns ### Request Format ```bash # Standard POST request with JSON body curl -X POST http://localhost:8081/api/v1/kv/mykey/put \ -H "Content-Type: application/json" \ -d '{"value": "myvalue"}' ``` ### Response Format **Success Response:** ```json { "data": { "id": "resource-id", "name": "resource-name", ... }, "meta": { "request_id": "uuid-v4", "timestamp": "2025-12-12T08:30:00Z" } } ``` **Error Response:** ```json { "error": { "code": "NOT_FOUND", "message": "Resource not found", "details": null }, "meta": { "request_id": "uuid-v4", "timestamp": "2025-12-12T08:30:00Z" } } ``` ### Authentication Most services support multi-tenancy via `org_id` and `project_id`: ```bash # Query parameters for filtering curl "http://localhost:8087/api/v1/vpcs?org_id=org-123&project_id=proj-456" # Request body for creation curl -X POST http://localhost:8087/api/v1/vpcs \ -H "Content-Type: application/json" \ -d '{ "name": "production-vpc", "org_id": "org-123", "project_id": "proj-456", "cidr_block": "10.0.0.0/16" }' ``` For IAM token-based auth: ```bash # Issue token TOKEN=$(curl -X POST http://localhost:8083/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{ "principal_id": "user-123", "scope_id": "project-456", "ttl_seconds": 3600 }' | jq -r '.data.token') # Use token in Authorization header curl -H "Authorization: Bearer $TOKEN" \ http://localhost:8084/api/v1/vms ``` --- ## 1. ChainFire (Distributed KV Store) **Port:** 8081 **Purpose:** Raft-based distributed key-value store with strong consistency ### Health Check ```bash curl http://localhost:8081/health ``` ### Cluster Status ```bash # Get cluster status (node_id, term, role, is_leader) curl http://localhost:8081/api/v1/cluster/status ``` **Response:** ```json { "data": { "node_id": 1, "cluster_id": "cluster-123", "term": 42, "role": "leader", "is_leader": true }, "meta": { ... } } ``` ### KV Operations **Put Key-Value:** ```bash curl -X POST http://localhost:8081/api/v1/kv/user:123/put \ -H "Content-Type: application/json" \ -d '{"value": "{\"name\":\"alice\",\"email\":\"alice@example.com\"}"}' ``` **Get Value:** ```bash curl http://localhost:8081/api/v1/kv/user:123 ``` **Response:** ```json { "data": { "key": "user:123", "value": "{\"name\":\"alice\",\"email\":\"alice@example.com\"}" }, "meta": { ... } } ``` **Delete Key:** ```bash curl -X POST http://localhost:8081/api/v1/kv/user:123/delete ``` **Range Scan (Prefix Query):** ```bash # List all keys starting with "user:" curl "http://localhost:8081/api/v1/kv?prefix=user:" ``` **Response:** ```json { "data": { "items": [ {"key": "user:123", "value": "{...}"}, {"key": "user:456", "value": "{...}"} ] }, "meta": { ... } } ``` ### Cluster Management **Add Cluster Member:** ```bash curl -X POST http://localhost:8081/api/v1/cluster/members \ -H "Content-Type: application/json" \ -d '{ "node_id": 2, "address": "192.168.1.102:50051" }' ``` --- ## 2. FlareDB (SQL Database) **Port:** 8082 **Purpose:** Distributed SQL database with KV backend ### Health Check ```bash curl http://localhost:8082/health ``` ### KV Operations **Put Key-Value:** ```bash curl -X PUT http://localhost:8082/api/v1/kv/config:db_version \ -H "Content-Type: application/json" \ -d '{ "value": "1.0.0", "namespace": "system" }' ``` **Get Value:** ```bash curl "http://localhost:8082/api/v1/kv/config:db_version?namespace=system" ``` **Response:** ```json { "data": { "key": "config:db_version", "value": "1.0.0", "namespace": "system" }, "meta": { ... } } ``` **Range Scan:** ```bash curl "http://localhost:8082/api/v1/scan?start=config:&end=config;&&namespace=system" ``` ### SQL Operations (Placeholder) **Execute SQL:** ```bash # Note: SQL endpoint is placeholder - use gRPC for full SQL functionality curl -X POST http://localhost:8082/api/v1/sql \ -H "Content-Type: application/json" \ -d '{ "query": "SELECT * FROM users WHERE id = 123" }' ``` **List Tables:** ```bash # Note: Placeholder endpoint - use gRPC for full functionality curl http://localhost:8082/api/v1/tables ``` --- ## 3. IAM (Identity & Access Management) **Port:** 8083 **Purpose:** Authentication, authorization, user and policy management ### Health Check ```bash curl http://localhost:8083/health ``` ### Token Operations **Issue Token:** ```bash curl -X POST http://localhost:8083/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{ "principal_id": "user-alice", "principal_type": "user", "scope_id": "project-prod", "ttl_seconds": 3600 }' ``` **Response:** ```json { "data": { "token": "eyJhbGciOiJIUzI1NiIs...", "expires_at": "2025-12-12T10:30:00Z" }, "meta": { ... } } ``` **Verify Token:** ```bash curl -X POST http://localhost:8083/api/v1/auth/verify \ -H "Content-Type: application/json" \ -d '{ "token": "eyJhbGciOiJIUzI1NiIs..." }' ``` **Response:** ```json { "data": { "valid": true, "principal_id": "user-alice", "scope_id": "project-prod", "expires_at": "2025-12-12T10:30:00Z" }, "meta": { ... } } ``` ### User Management **Create User:** ```bash curl -X POST http://localhost:8083/api/v1/users \ -H "Content-Type: application/json" \ -d '{ "id": "user-bob", "name": "Bob Smith", "email": "bob@example.com", "type": "user" }' ``` **List Users:** ```bash curl "http://localhost:8083/api/v1/users?scope_id=project-prod" ``` **Response:** ```json { "data": { "users": [ { "id": "user-alice", "name": "Alice Johnson", "email": "alice@example.com", "type": "user" }, { "id": "user-bob", "name": "Bob Smith", "email": "bob@example.com", "type": "user" } ] }, "meta": { ... } } ``` ### Project Management (Placeholder) ```bash # Note: Project management uses Scope/PolicyBinding in gRPC # These REST endpoints are placeholders curl http://localhost:8083/api/v1/projects curl -X POST http://localhost:8083/api/v1/projects \ -H "Content-Type: application/json" \ -d '{"name": "production", "org_id": "org-123"}' ``` --- ## 4. PlasmaVMC (Virtual Machine Controller) **Port:** 8084 **Purpose:** VM lifecycle management (create, start, stop, delete) ### Health Check ```bash curl http://localhost:8084/health ``` ### VM Operations **List VMs:** ```bash curl "http://localhost:8084/api/v1/vms?org_id=org-123&project_id=proj-456" ``` **Response:** ```json { "data": { "vms": [ { "id": "vm-001", "name": "web-server-01", "state": "Running", "cpus": 4, "memory_mb": 8192 }, { "id": "vm-002", "name": "db-server-01", "state": "Stopped", "cpus": 8, "memory_mb": 16384 } ] }, "meta": { ... } } ``` **Create VM:** ```bash curl -X POST http://localhost:8084/api/v1/vms \ -H "Content-Type: application/json" \ -d '{ "name": "app-server-03", "org_id": "org-123", "project_id": "proj-456", "vcpus": 2, "memory_mib": 4096, "hypervisor": "kvm", "image_id": "ubuntu-22.04", "disk_size_gb": 50 }' ``` **Response:** ```json { "data": { "id": "vm-003", "name": "app-server-03", "state": "Creating", "cpus": 2, "memory_mb": 4096 }, "meta": { ... } } ``` **Get VM Details:** ```bash curl "http://localhost:8084/api/v1/vms/vm-003?org_id=org-123&project_id=proj-456" ``` **Start VM:** ```bash curl -X POST "http://localhost:8084/api/v1/vms/vm-003/start?org_id=org-123&project_id=proj-456" ``` **Stop VM:** ```bash curl -X POST "http://localhost:8084/api/v1/vms/vm-003/stop?org_id=org-123&project_id=proj-456" \ -H "Content-Type: application/json" \ -d '{"force": false}' ``` **Delete VM:** ```bash curl -X DELETE "http://localhost:8084/api/v1/vms/vm-003?org_id=org-123&project_id=proj-456" ``` --- ## 5. k8shost (Kubernetes Host) **Port:** 8085 **Purpose:** Kubernetes pod/service/node management (kubelet replacement) ### Health Check ```bash curl http://localhost:8085/health ``` ### Pod Operations **List Pods:** ```bash # All namespaces curl http://localhost:8085/api/v1/pods # Specific namespace curl "http://localhost:8085/api/v1/pods?namespace=production" ``` **Response:** ```json { "data": { "pods": [ { "name": "nginx-deployment-7d8f9c5b6d-xk2p9", "namespace": "production", "phase": "Running", "pod_ip": "10.244.1.5", "node_name": "worker-01" } ] }, "meta": { ... } } ``` **Create Pod:** ```bash curl -X POST http://localhost:8085/api/v1/pods \ -H "Content-Type: application/json" \ -d '{ "name": "nginx-pod", "namespace": "production", "image": "nginx:1.21", "command": ["/bin/sh"], "args": ["-c", "nginx -g \"daemon off;\""] }' ``` **Delete Pod:** ```bash curl -X DELETE http://localhost:8085/api/v1/pods/production/nginx-pod ``` ### Service Operations **List Services:** ```bash curl "http://localhost:8085/api/v1/services?namespace=production" ``` **Response:** ```json { "data": { "services": [ { "name": "nginx-service", "namespace": "production", "type": "ClusterIP", "cluster_ip": "10.96.0.100", "ports": [ {"port": 80, "target_port": 8080, "protocol": "TCP"} ] } ] }, "meta": { ... } } ``` **Create Service:** ```bash curl -X POST http://localhost:8085/api/v1/services \ -H "Content-Type: application/json" \ -d '{ "name": "app-service", "namespace": "production", "service_type": "ClusterIP", "port": 80, "target_port": 8080, "selector": {"app": "nginx"} }' ``` **Delete Service:** ```bash curl -X DELETE http://localhost:8085/api/v1/services/production/app-service ``` ### Node Operations **List Nodes:** ```bash curl http://localhost:8085/api/v1/nodes ``` **Response:** ```json { "data": { "nodes": [ { "name": "worker-01", "status": "Ready", "capacity_cpu": "8", "capacity_memory": "16Gi", "allocatable_cpu": "7.5", "allocatable_memory": "14Gi" } ] }, "meta": { ... } } ``` --- ## 6. CreditService (Credit/Quota Management) **Port:** 8086 **Purpose:** Multi-tenant credit tracking, reservations, and billing ### Health Check ```bash curl http://localhost:8086/health ``` ### Wallet Operations **Create Wallet:** ```bash curl -X POST http://localhost:8086/api/v1/wallets \ -H "Content-Type: application/json" \ -d '{ "project_id": "proj-456", "org_id": "org-123", "initial_balance": 10000 }' ``` **Get Wallet Balance:** ```bash curl http://localhost:8086/api/v1/wallets/proj-456 ``` **Response:** ```json { "data": { "project_id": "proj-456", "org_id": "org-123", "balance": 10000, "reserved": 2500, "available": 7500, "currency": "JPY", "status": "active" }, "meta": { ... } } ``` **Top Up Credits:** ```bash curl -X POST http://localhost:8086/api/v1/wallets/proj-456/topup \ -H "Content-Type: application/json" \ -d '{ "amount": 5000, "description": "Monthly credit purchase" }' ``` **Get Transactions:** ```bash curl "http://localhost:8086/api/v1/wallets/proj-456/transactions?limit=10" ``` **Response:** ```json { "data": { "transactions": [ { "id": "txn-001", "project_id": "proj-456", "amount": 5000, "type": "deposit", "description": "Monthly credit purchase", "timestamp": "2025-12-12T08:00:00Z" }, { "id": "txn-002", "project_id": "proj-456", "amount": -1500, "type": "charge", "description": "VM usage charge", "resource_id": "vm-003", "timestamp": "2025-12-12T09:00:00Z" } ] }, "meta": { ... } } ``` ### Reservation Operations **Reserve Credits:** ```bash curl -X POST http://localhost:8086/api/v1/reservations \ -H "Content-Type: application/json" \ -d '{ "project_id": "proj-456", "amount": 2000, "description": "VM creation reservation", "resource_type": "vm", "resource_id": "vm-004", "ttl_seconds": 3600 }' ``` **Response:** ```json { "data": { "id": "rsv-001", "project_id": "proj-456", "amount": 2000, "status": "active", "expires_at": "2025-12-12T10:00:00Z" }, "meta": { ... } } ``` **Commit Reservation:** ```bash curl -X POST http://localhost:8086/api/v1/reservations/rsv-001/commit \ -H "Content-Type: application/json" \ -d '{ "actual_amount": 1800, "resource_id": "vm-004" }' ``` **Release Reservation:** ```bash curl -X POST http://localhost:8086/api/v1/reservations/rsv-001/release \ -H "Content-Type: application/json" \ -d '{ "reason": "VM creation failed" }' ``` --- ## 7. PrismNET (Network Management) **Port:** 8087 **Purpose:** Multi-tenant VPC, subnet, and port management ### Health Check ```bash curl http://localhost:8087/health ``` ### VPC Operations **List VPCs:** ```bash curl "http://localhost:8087/api/v1/vpcs?org_id=org-123&project_id=proj-456" ``` **Response:** ```json { "data": { "vpcs": [ { "id": "vpc-001", "name": "production-vpc", "org_id": "org-123", "project_id": "proj-456", "cidr_block": "10.0.0.0/16", "description": "Production environment VPC", "status": "active" } ] }, "meta": { ... } } ``` **Create VPC:** ```bash curl -X POST http://localhost:8087/api/v1/vpcs \ -H "Content-Type: application/json" \ -d '{ "name": "staging-vpc", "org_id": "org-123", "project_id": "proj-456", "cidr_block": "172.16.0.0/16", "description": "Staging environment VPC" }' ``` **Get VPC:** ```bash curl "http://localhost:8087/api/v1/vpcs/vpc-001?org_id=org-123&project_id=proj-456" ``` **Delete VPC:** ```bash curl -X DELETE "http://localhost:8087/api/v1/vpcs/vpc-001?org_id=org-123&project_id=proj-456" ``` ### Subnet Operations **List Subnets:** ```bash curl "http://localhost:8087/api/v1/subnets?vpc_id=vpc-001&org_id=org-123&project_id=proj-456" ``` **Response:** ```json { "data": { "subnets": [ { "id": "subnet-001", "name": "web-subnet", "vpc_id": "vpc-001", "cidr_block": "10.0.1.0/24", "gateway_ip": "10.0.1.1", "description": "Web tier subnet", "status": "active" }, { "id": "subnet-002", "name": "db-subnet", "vpc_id": "vpc-001", "cidr_block": "10.0.2.0/24", "gateway_ip": "10.0.2.1", "description": "Database tier subnet", "status": "active" } ] }, "meta": { ... } } ``` **Create Subnet:** ```bash curl -X POST http://localhost:8087/api/v1/subnets \ -H "Content-Type: application/json" \ -d '{ "name": "app-subnet", "vpc_id": "vpc-001", "cidr_block": "10.0.3.0/24", "gateway_ip": "10.0.3.1", "description": "Application tier subnet" }' ``` **Delete Subnet:** ```bash curl -X DELETE "http://localhost:8087/api/v1/subnets/subnet-003?org_id=org-123&project_id=proj-456&vpc_id=vpc-001" ``` --- ## Complete Workflow Examples ### Example 1: Deploy VM with Networking ```bash # 1. Create VPC VPC_ID=$(curl -s -X POST http://localhost:8087/api/v1/vpcs \ -H "Content-Type: application/json" \ -d '{ "name": "app-vpc", "org_id": "org-123", "project_id": "proj-456", "cidr_block": "10.100.0.0/16" }' | jq -r '.data.id') # 2. Create Subnet SUBNET_ID=$(curl -s -X POST http://localhost:8087/api/v1/subnets \ -H "Content-Type: application/json" \ -d "{ \"name\": \"app-subnet\", \"vpc_id\": \"$VPC_ID\", \"cidr_block\": \"10.100.1.0/24\", \"gateway_ip\": \"10.100.1.1\" }" | jq -r '.data.id') # 3. Reserve Credits RSV_ID=$(curl -s -X POST http://localhost:8086/api/v1/reservations \ -H "Content-Type: application/json" \ -d '{ "project_id": "proj-456", "amount": 5000, "resource_type": "vm", "ttl_seconds": 3600 }' | jq -r '.data.id') # 4. Create VM VM_ID=$(curl -s -X POST http://localhost:8084/api/v1/vms \ -H "Content-Type: application/json" \ -d '{ "name": "app-server", "org_id": "org-123", "project_id": "proj-456", "vcpus": 4, "memory_mib": 8192, "hypervisor": "kvm" }' | jq -r '.data.id') # 5. Start VM curl -X POST "http://localhost:8084/api/v1/vms/$VM_ID/start?org_id=org-123&project_id=proj-456" # 6. Commit Reservation curl -X POST "http://localhost:8086/api/v1/reservations/$RSV_ID/commit" \ -H "Content-Type: application/json" \ -d "{ \"actual_amount\": 4500, \"resource_id\": \"$VM_ID\" }" echo "VM deployed: $VM_ID in VPC: $VPC_ID, Subnet: $SUBNET_ID" ``` ### Example 2: Deploy Kubernetes Pod with Service ```bash # 1. Create Pod curl -X POST http://localhost:8085/api/v1/pods \ -H "Content-Type: application/json" \ -d '{ "name": "nginx-app", "namespace": "production", "image": "nginx:1.21" }' # 2. Create Service curl -X POST http://localhost:8085/api/v1/services \ -H "Content-Type: application/json" \ -d '{ "name": "nginx-service", "namespace": "production", "service_type": "ClusterIP", "port": 80, "target_port": 80, "selector": {"app": "nginx"} }' # 3. Verify Pod Status curl "http://localhost:8085/api/v1/pods?namespace=production" | jq '.data.pods[] | select(.name=="nginx-app")' ``` ### Example 3: User Authentication Flow ```bash # 1. Create User curl -X POST http://localhost:8083/api/v1/users \ -H "Content-Type: application/json" \ -d '{ "id": "user-charlie", "name": "Charlie Brown", "email": "charlie@example.com", "type": "user" }' # 2. Issue Token TOKEN=$(curl -s -X POST http://localhost:8083/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{ "principal_id": "user-charlie", "scope_id": "project-prod", "ttl_seconds": 7200 }' | jq -r '.data.token') # 3. Verify Token curl -X POST http://localhost:8083/api/v1/auth/verify \ -H "Content-Type: application/json" \ -d "{\"token\": \"$TOKEN\"}" # 4. Use Token for API Call curl -H "Authorization: Bearer $TOKEN" \ "http://localhost:8084/api/v1/vms?org_id=org-123&project_id=project-prod" ``` --- ## Debugging Tips ### Check All Services Health ```bash #!/bin/bash services=( "ChainFire:8081" "FlareDB:8082" "IAM:8083" "PlasmaVMC:8084" "k8shost:8085" "CreditService:8086" "PrismNET:8087" ) for svc in "${services[@]}"; do name="${svc%%:*}" port="${svc##*:}" echo -n "$name ($port): " curl -s http://localhost:$port/health | jq -r '.data.status // "ERROR"' done ``` ### Verbose curl for Debugging ```bash # Show request/response headers curl -v http://localhost:8081/health # Show timing information curl -w "@-" -o /dev/null -s http://localhost:8081/health <<'EOF' time_namelookup: %{time_namelookup}\n time_connect: %{time_connect}\n time_total: %{time_total}\n EOF ``` ### Pretty-print JSON Responses ```bash # Install jq if not available # Ubuntu/Debian: sudo apt-get install jq # macOS: brew install jq curl http://localhost:8087/api/v1/vpcs | jq '.' ``` --- ## Migration from gRPC If you have existing gRPC client code, here's how to migrate: ### gRPC (Before) ```rust use chainfire_client::ChainFireClient; let mut client = ChainFireClient::connect("http://localhost:50051").await?; let response = client.get(tonic::Request::new(GetRequest { key: "mykey".to_string(), })).await?; println!("Value: {}", response.into_inner().value); ``` ### REST (After) ```bash curl http://localhost:8081/api/v1/kv/mykey | jq -r '.data.value' ``` Or with any HTTP client library: ```python import requests response = requests.get('http://localhost:8081/api/v1/kv/mykey') data = response.json() print(f"Value: {data['data']['value']}") ``` --- ## Error Handling All services return consistent error responses: ### Common HTTP Status Codes | Code | Meaning | Example | |------|---------|---------| | 200 | OK | Successful GET/POST | | 201 | Created | Resource created | | 400 | Bad Request | Invalid JSON or missing required fields | | 404 | Not Found | Resource doesn't exist | | 409 | Conflict | Resource already exists or state conflict | | 500 | Internal Server Error | Service error | | 503 | Service Unavailable | Service not ready (e.g., Raft not leader) | ### Error Response Example ```bash curl -X POST http://localhost:8087/api/v1/vpcs \ -H "Content-Type: application/json" \ -d '{"name": "invalid"}' ``` **Response (400 Bad Request):** ```json { "error": { "code": "VALIDATION_ERROR", "message": "cidr_block is required", "details": { "field": "cidr_block", "constraint": "required" } }, "meta": { "request_id": "req-12345", "timestamp": "2025-12-12T08:30:00Z" } } ``` ### Handling Errors in Scripts ```bash #!/bin/bash response=$(curl -s -w "\n%{http_code}" http://localhost:8084/api/v1/vms/invalid-id) body=$(echo "$response" | head -n -1) status=$(echo "$response" | tail -n 1) if [ "$status" -ne 200 ]; then echo "Error: $(echo $body | jq -r '.error.message')" exit 1 fi echo "Success: $body" ``` --- ## Performance Considerations ### Connection Reuse For multiple requests, reuse connections: ```bash # Single connection for multiple requests curl -K - <