# rdev v0.4.0 - API Server

**Date**: 2026-01-24
**Status**: Ready for deployment

## Summary

Go REST API server for controlling claudebox pods. External clients (Discord bots, CLI tools, etc.) can now interact with Claude Code via HTTP endpoints with SSE streaming for real-time output.

## What Was Built

### Go API Server (`rdev-api`)

A chi-based HTTP server with:
- Project discovery and status
- Command execution (claude, shell, git)
- SSE streaming for real-time output
- OpenAPI documentation via Scalar

### API Endpoints

| Method | Path | Description |
|--------|------|-------------|
| GET | `/health` | Health check |
| GET | `/ready` | Readiness check |
| GET | `/docs` | Scalar API documentation |
| GET | `/openapi.json` | OpenAPI 3.0 specification |
| GET | `/projects` | List available projects |
| GET | `/projects/{id}` | Get project details |
| POST | `/projects/{id}/claude` | Run Claude command |
| POST | `/projects/{id}/shell` | Run shell command |
| POST | `/projects/{id}/git` | Run git command |
| GET | `/projects/{id}/events` | SSE stream for output |

### Packages Created

```
cmd/rdev-api/
└── main.go              # Entry point, OpenAPI spec

pkg/api/
├── app.go               # HTTP server chassis
├── response.go          # JSON response helpers
└── openapi.go           # OpenAPI spec builder

internal/
├── handlers/
│   └── projects.go      # HTTP handlers + SSE streaming
├── executor/
│   └── executor.go      # kubectl exec wrapper
└── projects/
    └── registry.go      # Project discovery
```

### Kubernetes Resources

- **Deployment**: `rdev-api` - Single replica
- **Service**: `rdev-api` - ClusterIP on port 8080
- **ServiceAccount**: `rdev-api`
- **Role/RoleBinding**: Permissions for pod exec

### RBAC Permissions

```yaml
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get"]
```

## Files Created

```
Dockerfile.api                         # API server image
cmd/rdev-api/main.go                   # Entry point
pkg/api/app.go                         # HTTP chassis
pkg/api/response.go                    # Response helpers
pkg/api/openapi.go                     # OpenAPI builder
internal/handlers/projects.go          # Handlers + SSE
internal/executor/executor.go          # kubectl exec
internal/projects/registry.go          # Project registry
deployments/k8s/base/rdev-api.yaml     # Deployment + Service
deployments/k8s/base/rbac.yaml         # RBAC
go.mod, go.sum                         # Go modules
```

## Dependencies

```
github.com/go-chi/chi/v5         # HTTP router
github.com/bdpiprava/scalar-go   # API documentation
```

## Deployment Instructions

### 1. Build Images

```bash
cd /path/to/rdev

# Build both claudebox and api images
./scripts/build-push.sh v0.4.0

# Or just the api
./scripts/build-push.sh v0.4.0 api
```

### 2. Complete Prerequisites

Ensure v0.2 and v0.3 are deployed:
- Deploy keys configured for projects
- Secrets updated with base64 private keys
- claudebox image v0.3.0 with git config

### 3. Deploy

```bash
export KUBECONFIG=~/.kube/orchard9-k3sf.yaml
kubectl apply -k deployments/k8s/base
```

### 4. Verify

```bash
# Check API is running
kubectl get pods -n rdev -l app=rdev-api

# Port forward for testing
kubectl port-forward -n rdev svc/rdev-api 8080:8080

# Test health endpoint
curl http://localhost:8080/health

# Test projects list
curl http://localhost:8080/projects

# Test Claude command
curl -X POST http://localhost:8080/projects/pantheon/claude \
  -H "Content-Type: application/json" \
  -d '{"prompt": "what files are in this project?"}'

# View API docs
open http://localhost:8080/docs
```

## Usage Examples

### Run Claude Command

```bash
# Start command
curl -X POST http://rdev-api.rdev.svc:8080/projects/pantheon/claude \
  -H "Content-Type: application/json" \
  -d '{"prompt": "fix the bug in auth handler"}'

# Response
{
  "data": {
    "id": "cmd-pantheon-001",
    "project": "pantheon",
    "type": "claude",
    "status": "running",
    "stream_url": "/projects/pantheon/events?stream_id=cmd-pantheon-001"
  },
  "meta": {"request_id": "...", "timestamp": "..."}
}
```

### Stream Output (SSE)

```javascript
const events = new EventSource(
  'http://rdev-api.rdev.svc:8080/projects/pantheon/events?stream_id=cmd-pantheon-001'
);

events.addEventListener('output', (e) => {
  const data = JSON.parse(e.data);
  console.log(`[${data.stream}] ${data.line}`);
});

events.addEventListener('complete', (e) => {
  const data = JSON.parse(e.data);
  console.log(`Done: exit=${data.exit_code}, ${data.duration_ms}ms`);
  events.close();
});
```

### Run Shell Command

```bash
curl -X POST http://rdev-api.rdev.svc:8080/projects/pantheon/shell \
  -H "Content-Type: application/json" \
  -d '{"command": "go test ./..."}'
```

### Run Git Command

```bash
curl -X POST http://rdev-api.rdev.svc:8080/projects/pantheon/git \
  -H "Content-Type: application/json" \
  -d '{"args": ["status"]}'
```

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                       rdev namespace                         │
│                                                              │
│  ┌──────────────┐                                           │
│  │  rdev-api    │                                           │
│  │  (Go server) │                                           │
│  │              │                                           │
│  │  /projects   │  kubectl exec                             │
│  │  /claude     │─────────────────┐                         │
│  │  /shell      │                 │                         │
│  │  /git        │                 ▼                         │
│  │  /events     │  ┌──────────────────────────────────────┐ │
│  └──────────────┘  │         claudebox pods               │ │
│                    │                                      │ │
│                    │  ┌────────────────┐ ┌──────────────┐ │ │
│                    │  │claudebox-      │ │claudebox-    │ │ │
│                    │  │pantheon-0      │ │aeries-0      │ │ │
│                    │  │                │ │              │ │ │
│                    │  │ Claude Code    │ │ Claude Code  │ │ │
│                    │  │ /workspace     │ │ /workspace   │ │ │
│                    │  └────────────────┘ └──────────────┘ │ │
│                    └──────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```

## What's Next (v0.5)

Enhanced SSE streaming:
- Output buffering and chunking
- Connection management (heartbeats, reconnection)
- Event filtering by stream_id
- Better error handling

## Troubleshooting

### API returns 404 for project
- Check project registry includes the project
- Verify claudebox pod exists: `kubectl get pods -n rdev`

### Commands fail with "permission denied"
- Check RBAC is applied: `kubectl get role rdev-api -n rdev`
- Verify ServiceAccount is bound: `kubectl get rolebinding rdev-api -n rdev`

### SSE not receiving events
- Ensure stream_id matches the command ID
- Check for Connection: keep-alive in client
- Verify no proxy is buffering responses
