diff --git a/.env.local.example b/.env.local.example new file mode 100644 index 0000000..0ea58e3 --- /dev/null +++ b/.env.local.example @@ -0,0 +1,18 @@ +# rdev-api local development configuration +# Copy to .env.local and customize as needed +# Usage: cp .env.local.example .env.local + +# Server +PORT=8080 + +# Database (matches docker-compose.yaml defaults) +DB_HOST=localhost +DB_PORT=5433 +DB_USER=appuser +DB_PASSWORD=localdev +DB_NAME=rdev +DB_SSL_MODE=disable + +# Authentication +# Fixed dev admin key - DO NOT use in production +RDEV_ADMIN_KEY=rdev_sk_devadmin_0123456789abcdef0123456789abcdef diff --git a/.gitignore b/.gitignore index 8f822b5..7641819 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ *.key *.pem +# Local development +.env.local + # OS .DS_Store Thumbs.db diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e7af747 --- /dev/null +++ b/Makefile @@ -0,0 +1,86 @@ +# rdev-api development commands +# Run 'make help' to see available targets + +.PHONY: help setup run test build clean db-up db-down db-reset db-shell db-logs + +# Load .env.local if it exists +ifneq (,$(wildcard .env.local)) + include .env.local +endif + +# Default values (can be overridden by .env.local) +PORT ?= 8080 +DB_HOST ?= localhost +DB_PORT ?= 5433 +DB_USER ?= appuser +DB_PASSWORD ?= localdev +DB_NAME ?= rdev +DB_SSL_MODE ?= disable +RDEV_ADMIN_KEY ?= rdev_sk_devadmin_0123456789abcdef0123456789abcdef + +# Export all variables to child processes +export PORT DB_HOST DB_PORT DB_USER DB_PASSWORD DB_NAME DB_SSL_MODE RDEV_ADMIN_KEY + +help: ## Show this help + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' + +setup: ## First-time setup: copy env template + @if [ ! -f .env.local ]; then \ + cp .env.local.example .env.local; \ + echo "Created .env.local from template"; \ + else \ + echo ".env.local already exists"; \ + fi + +run: ## Run the API server locally + go run ./cmd/rdev-api + +test: ## Run all tests + go test -v ./... + +build: ## Build the binary + CGO_ENABLED=0 go build -o rdev-api ./cmd/rdev-api + +clean: ## Remove build artifacts + rm -f rdev-api + +# Database commands +db-up: ## Start local PostgreSQL container + docker compose up -d postgres + @echo "Waiting for postgres to be ready..." + @until docker compose exec -T postgres pg_isready -U $(DB_USER) -d $(DB_NAME) > /dev/null 2>&1; do \ + sleep 1; \ + done + @echo "PostgreSQL is ready on port $(DB_PORT)" + +db-down: ## Stop local PostgreSQL container + docker compose down + +db-reset: ## Reset database (destroy and recreate) + docker compose down -v + $(MAKE) db-up + +db-shell: ## Open psql shell to local database + docker compose exec postgres psql -U $(DB_USER) -d $(DB_NAME) + +db-logs: ## View PostgreSQL logs + docker compose logs -f postgres + +# Combined commands +dev: db-up run ## Start database and run API + +# Testing helpers +curl-health: ## Test health endpoint + @curl -s http://localhost:$(PORT)/health | jq . + +curl-projects: ## Test projects endpoint (requires auth) + @curl -s -H "Authorization: Bearer $(RDEV_ADMIN_KEY)" http://localhost:$(PORT)/projects | jq . + +curl-keys: ## Test keys endpoint (requires auth) + @curl -s -H "Authorization: Bearer $(RDEV_ADMIN_KEY)" http://localhost:$(PORT)/keys | jq . + +create-test-key: ## Create a test API key + @curl -s -X POST -H "Authorization: Bearer $(RDEV_ADMIN_KEY)" \ + -H "Content-Type: application/json" \ + -d '{"name": "test-key", "scopes": ["projects:read"], "expires_in": "30d"}' \ + http://localhost:$(PORT)/keys | jq . diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..4caa566 --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,183 @@ +# rdev-api Developer Quickstart + +Get the API running locally in under 2 minutes. + +## Prerequisites + +- Go 1.21+ +- Docker (for PostgreSQL) +- jq (optional, for pretty JSON output) + +## Quick Start + +```bash +# 1. Clone and enter the repo +cd rdev + +# 2. First-time setup (creates .env.local) +make setup + +# 3. Start PostgreSQL +make db-up + +# 4. Run the API +make run +``` + +The API will: +- Connect to PostgreSQL on port 5433 +- Auto-run database migrations +- Start serving on http://localhost:8080 + +## Verify It Works + +```bash +# Health check (no auth required) +curl http://localhost:8080/health | jq . + +# API docs +open http://localhost:8080/docs + +# List projects (requires auth) +make curl-projects + +# Create a test API key +make create-test-key +``` + +## Available Commands + +Run `make help` to see all commands: + +| Command | Description | +|---------|-------------| +| `make setup` | First-time setup: create .env.local | +| `make run` | Run the API server | +| `make dev` | Start database + run API | +| `make test` | Run all tests | +| `make build` | Build the binary | +| `make db-up` | Start PostgreSQL container | +| `make db-down` | Stop PostgreSQL container | +| `make db-reset` | Destroy and recreate database | +| `make db-shell` | Open psql shell | +| `make curl-health` | Test health endpoint | +| `make curl-projects` | Test projects endpoint | +| `make curl-keys` | Test keys endpoint | +| `make create-test-key` | Create a test API key | + +## Configuration + +Edit `.env.local` to customize: + +```bash +# Server +PORT=8080 + +# Database +DB_HOST=localhost +DB_PORT=5433 +DB_USER=appuser +DB_PASSWORD=localdev +DB_NAME=rdev +DB_SSL_MODE=disable + +# Authentication (dev admin key) +RDEV_ADMIN_KEY=rdev_sk_devadmin_0123456789abcdef0123456789abcdef +``` + +## API Authentication + +All endpoints except `/health`, `/ready`, `/docs`, and `/openapi.json` require authentication. + +Use the `Authorization` header: + +```bash +curl -H "Authorization: Bearer rdev_sk_devadmin_..." http://localhost:8080/projects +``` + +Or the `X-API-Key` header: + +```bash +curl -H "X-API-Key: rdev_sk_devadmin_..." http://localhost:8080/projects +``` + +### Creating API Keys + +```bash +# Using the Makefile helper +make create-test-key + +# Or manually +curl -X POST http://localhost:8080/keys \ + -H "Authorization: Bearer $RDEV_ADMIN_KEY" \ + -H "Content-Type: application/json" \ + -d '{"name": "my-key", "scopes": ["projects:read"], "expires_in": "30d"}' +``` + +### Available Scopes + +| Scope | Description | +|-------|-------------| +| `projects:read` | List and view projects | +| `projects:execute` | Run commands (claude, shell, git) | +| `keys:read` | List API keys | +| `keys:write` | Create and revoke keys | +| `admin` | Full access | + +## Project Structure + +``` +rdev/ +├── cmd/rdev-api/ # API entry point +├── internal/ +│ ├── auth/ # Authentication (keys, middleware) +│ ├── db/ # Database connection + migrations +│ ├── handlers/ # HTTP handlers +│ ├── executor/ # kubectl exec wrapper +│ └── projects/ # Project registry +├── pkg/api/ # HTTP server chassis +├── docker-compose.yaml # Local PostgreSQL +├── Makefile # Dev commands +└── .env.local # Local config (gitignored) +``` + +## Troubleshooting + +### Port 5432 already in use + +The default port is 5433 to avoid conflicts with local PostgreSQL. If you still have issues: + +```bash +# Check what's using the port +lsof -i :5433 + +# Or change the port in .env.local and docker-compose.yaml +``` + +### Database connection errors + +```bash +# Reset the database +make db-reset + +# Check PostgreSQL is running +docker compose ps + +# View PostgreSQL logs +make db-logs +``` + +### Permission denied on /projects + +Ensure you're using the admin key from `.env.local`: + +```bash +source .env.local +curl -H "Authorization: Bearer $RDEV_ADMIN_KEY" http://localhost:8080/projects +``` + +## Next Steps + +- View the API documentation at http://localhost:8080/docs +- Create application-specific API keys for your services +- See `history/` for version history and architecture decisions diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..cdf8e7d --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,23 @@ +# Local development environment for rdev-api +# Usage: docker compose up -d + +services: + postgres: + image: postgres:15-alpine + container_name: rdev-postgres + environment: + POSTGRES_USER: appuser + POSTGRES_PASSWORD: localdev + POSTGRES_DB: rdev + ports: + - "5433:5432" # Use 5433 to avoid conflicts with local postgres + volumes: + - rdev-postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U appuser -d rdev"] + interval: 5s + timeout: 5s + retries: 5 + +volumes: + rdev-postgres-data: