rdev/history/v0.4.0.md
jordan 0960b17eb2 feat: Implement v0.2-v0.4 (workspaces, git, API)
v0.2 - Real Workspaces:
- Project-specific claudebox StatefulSets (pantheon, aeries)
- Init containers for git clone via SSH
- Deploy key secrets template
- Project ConfigMaps for CLAUDE.md

v0.3 - Git Integration:
- Dockerfile with rdev-bot git identity
- openssh-client for SSH operations
- Image version bump to v0.3.0

v0.4 - API Server:
- Go REST API with chi router
- Endpoints: /projects, /claude, /shell, /git, /events
- SSE streaming for real-time output
- OpenAPI docs via Scalar at /docs
- Kubernetes RBAC for pod exec
- Executor and project registry packages

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 21:07:00 -07:00

260 lines
8.0 KiB
Markdown

# 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