# Hatch API — Deployment Guide

## Overview

The Hatch API (`hatch.surf`) is a **Go backend** deployed via **Docker Compose** on the production server.

**Key principle**: All changes MUST go through the git repository and automated deployment. Never edit files directly on the server.

---

## Repository

**Location**: `/home/nara/apps/web/`

**Git Remotes**:
- `github` → `el-foundation/hatch-surf` (Gitea, source of truth)
- `origin` → `el-foundation/hatch-surf` (Gitea push-mirror)

**Structure**:
```
cmd/hatch/              # Go server entrypoint
internal/               # Go packages (handler, store, face, etc.)
Dockerfile              # Multi-stage Docker build (Go → scratch)
docker-compose.yml      # Container orchestration (hatch + caddy)
Caddyfile               # Caddy reverse proxy config
deploy.sh               # Deployment script
```

---

## Deployment Flow

### Automatic (Recommended)

1. Merge PR to `main`
2. Gitea webhook triggers `gitea-webhook.py`
3. Script runs `deploy.sh` automatically

### Manual

```bash
cd /home/nara/apps/web
./deploy.sh
```

**What `deploy.sh` does**:
1. `git pull github main` — fetches latest from GitHub (source of truth)
2. `git push origin main` — syncs to Gitea (push-mirror)
3. `docker compose down` — stops current containers
4. `docker compose build hatch` — rebuilds the Go binary in a multi-stage build
5. `docker compose --profile with-caddy up -d` — starts hatch + caddy
6. Verifies health endpoint responds 200

---

## Docker Setup

**Services**:
| Service  | Image          | Port  | Purpose                |
|----------|----------------|-------|------------------------|
| `hatch`  | web-hatch      | 8080  | Go API server          |
| `caddy`  | caddy:2-alpine | 80/443| Reverse proxy + TLS    |

**Profiles**:
- Default: `hatch` only (API on port 8080)
- `with-caddy`: `hatch` + `caddy` (full HTTPS via Let's Encrypt)

**Check status**:
```bash
docker compose ps
docker compose logs hatch
docker compose logs caddy
```

---

## Environment Variables

Configure in `.env` or pass to Docker Compose:

| Variable               | Default              | Description                          |
|------------------------|----------------------|--------------------------------------|
| `HATCH_HOSTNAME`       | `localhost`          | Public hostname for TLS cert         |
| `HATCH_BASE_URL`       | `http://localhost`   | Base URL for SSE and self-references |
| `FACE_SERVICE_ENABLED` | `false`              | Enable AWS Rekognition face search   |
| `AWS_REGION`           | `us-east-1`          | AWS region for Rekognition           |
| `REKOGNITION_COLLECTION` | `hatch-faces`      | Rekognition collection ID            |
| `REDIS_URL`            | —                    | Redis URL (optional, for caching)    |

---

## Making Changes

### 1. Edit Go source

```bash
cd /home/nara/apps/web
vim cmd/hatch/main.go       # Server entrypoint
vim internal/handler/       # HTTP handlers
vim internal/face/          # Face detection service
vim internal/store/         # Database layer
```

### 2. Build and test locally

```bash
go build ./cmd/hatch/
go test ./...
```

### 3. Commit and push

```bash
git add .
git commit -m "Description of changes"
git push origin main
```

### 4. Deploy

Either wait for webhook or run manually:
```bash
./deploy.sh
```

### 5. Verify

```bash
curl -s http://localhost:8080/healthz
curl -s http://localhost:8080/readyz
```

---

## Common Mistakes to Avoid

❌ **DON'T**: Edit files directly inside the Docker container  
❌ **DON'T**: Commit without testing  
❌ **DON'T**: Use `go run` in production  

✅ **DO**: Test with `go test ./...` before committing  
✅ **DO**: Use `docker compose build` for production builds  
✅ **DO**: Check health endpoints after deployment  

---

## Rollback

If a deployment causes issues:

```bash
cd /home/nara/apps/web

# Revert to previous version
git revert HEAD
git push origin main

# Redeploy
./deploy.sh
```

---

## API Endpoints

| Method | Path                          | Description                     |
|--------|-------------------------------|---------------------------------|
| GET    | `/healthz`                    | Liveness probe                  |
| GET    | `/readyz`                     | Readiness probe (checks DB)     |
| GET    | `/api/v1/spaces`              | List public spaces              |
| POST   | `/api/v1/spaces`              | Create a space                  |
| GET    | `/api/v1/spaces/{slug}`       | Get space by slug               |
| POST   | `/api/v1/spaces/{slug}/photos`| Upload photo to space           |
| POST   | `/api/v1/face/search`         | Search faces by image           |
| GET    | `/e/{endpointID}`             | Inspect captured requests       |
| GET    | `/e/{endpointID}/events`      | SSE stream for live updates     |

---

## Troubleshooting

**Container not starting**:
```bash
docker compose logs hatch
docker compose logs caddy
```

**Health check failing**:
```bash
curl -v http://localhost:8080/healthz
docker compose exec hatch /bin/hatch  # Check binary exists
```

**Database issues**:
```bash
# SQLite database is persisted in a Docker volume
docker volume ls | grep hatch-data
docker run --rm -v hatch-data:/data alpine ls -la /data/
```

**Port conflict**:
```bash
sudo lsof -i :8080
# Kill conflicting process or change port in docker-compose.yml
```

---

## Integration Tests

Integration tests require AWS credentials (build tag: `integration`):

```bash
export AWS_REGION=us-east-1
export REKOGNITION_COLLECTION=hatch-faces-test
go test -tags=integration ./internal/face/... -v
```

Performance benchmarks (build tag: `performance`):

```bash
go test -tags=performance -bench=. ./internal/face/...
```

---

## Contact

- **CTO**: Jordan Patel
- **Repository**: `/home/nara/apps/web/`
- **API**: http://localhost:8080 (internal) / https://hatch.surf (public)
