feat(#93): implement agent spawn via federation

Implements FED-010: Agent Spawn via Federation feature that enables
spawning and managing Claude agents on remote federated Mosaic Stack
instances via COMMAND message type.

Features:
- Federation agent command types (spawn, status, kill)
- FederationAgentService for handling agent operations
- Integration with orchestrator's agent spawner/lifecycle services
- API endpoints for spawning, querying status, and killing agents
- Full command routing through federation COMMAND infrastructure
- Comprehensive test coverage (12/12 tests passing)

Architecture:
- Hub → Spoke: Spawn agents on remote instances
- Command flow: FederationController → FederationAgentService →
  CommandService → Remote Orchestrator
- Response handling: Remote orchestrator returns agent status/results
- Security: Connection validation, signature verification

Files created:
- apps/api/src/federation/types/federation-agent.types.ts
- apps/api/src/federation/federation-agent.service.ts
- apps/api/src/federation/federation-agent.service.spec.ts

Files modified:
- apps/api/src/federation/command.service.ts (agent command routing)
- apps/api/src/federation/federation.controller.ts (agent endpoints)
- apps/api/src/federation/federation.module.ts (service registration)
- apps/orchestrator/src/api/agents/agents.controller.ts (status endpoint)
- apps/orchestrator/src/api/agents/agents.module.ts (lifecycle integration)

Testing:
- 12/12 tests passing for FederationAgentService
- All command service tests passing
- TypeScript compilation successful
- Linting passed

Refs #93

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-02-03 14:37:06 -06:00
parent a8c8af21e5
commit 12abdfe81d
405 changed files with 13545 additions and 2153 deletions

View File

@@ -36,6 +36,7 @@ docker compose logs -f
```
That's it! Your Mosaic Stack is now running:
- Web: http://localhost:3000
- API: http://localhost:3001
- PostgreSQL: localhost:5432
@@ -46,6 +47,7 @@ That's it! Your Mosaic Stack is now running:
Mosaic Stack uses Docker Compose profiles to enable optional services:
### Core Services (Always Active)
- `postgres` - PostgreSQL database
- `valkey` - Valkey cache
- `api` - Mosaic API
@@ -54,6 +56,7 @@ Mosaic Stack uses Docker Compose profiles to enable optional services:
### Optional Services (Profiles)
#### Traefik (Reverse Proxy)
```bash
# Start with bundled Traefik
docker compose --profile traefik-bundled up -d
@@ -63,11 +66,13 @@ COMPOSE_PROFILES=traefik-bundled
```
Services included:
- `traefik` - Traefik reverse proxy with dashboard (http://localhost:8080)
See [Traefik Integration Guide](traefik.md) for detailed configuration options including upstream mode.
#### Authentik (OIDC Provider)
```bash
# Start with Authentik
docker compose --profile authentik up -d
@@ -77,12 +82,14 @@ COMPOSE_PROFILES=authentik
```
Services included:
- `authentik-postgres` - Authentik database
- `authentik-redis` - Authentik cache
- `authentik-server` - Authentik OIDC server (http://localhost:9000)
- `authentik-worker` - Authentik background worker
#### Ollama (AI Service)
```bash
# Start with Ollama
docker compose --profile ollama up -d
@@ -92,9 +99,11 @@ COMPOSE_PROFILES=ollama
```
Services included:
- `ollama` - Ollama LLM service (http://localhost:11434)
#### All Services
```bash
# Start everything
docker compose --profile full up -d
@@ -122,6 +131,7 @@ docker compose --profile full up -d
Use external services for production:
1. Copy override template:
```bash
cp docker-compose.override.yml.example docker-compose.override.yml
```
@@ -145,6 +155,7 @@ Docker automatically merges `docker-compose.yml` and `docker-compose.override.ym
Mosaic Stack uses two Docker networks to organize service communication:
#### mosaic-internal (Backend Services)
- **Purpose**: Isolates database and cache services
- **Services**:
- PostgreSQL (main database)
@@ -159,6 +170,7 @@ Mosaic Stack uses two Docker networks to organize service communication:
- No direct external access to database/cache ports (unless explicitly exposed)
#### mosaic-public (Frontend Services)
- **Purpose**: Services that need external network access
- **Services**:
- Mosaic API (needs to reach Authentik OIDC and external Ollama)
@@ -298,11 +310,13 @@ JWT_SECRET=change-this-to-a-random-secret
### Service Won't Start
Check logs:
```bash
docker compose logs <service-name>
```
Common issues:
- Port already in use: Change port in `.env`
- Health check failing: Wait longer or check service logs
- Missing environment variables: Check `.env` file
@@ -310,11 +324,13 @@ Common issues:
### Database Connection Issues
1. Verify PostgreSQL is healthy:
```bash
docker compose ps postgres
```
2. Check database logs:
```bash
docker compose logs postgres
```
@@ -327,6 +343,7 @@ Common issues:
### Performance Issues
1. Adjust PostgreSQL settings in `.env`:
```bash
POSTGRES_SHARED_BUFFERS=512MB
POSTGRES_EFFECTIVE_CACHE_SIZE=2GB
@@ -334,6 +351,7 @@ Common issues:
```
2. Adjust Valkey memory:
```bash
VALKEY_MAXMEMORY=512mb
```
@@ -394,6 +412,7 @@ docker run --rm -v mosaic-postgres-data:/data -v $(pwd):/backup alpine tar czf /
### Monitoring
Consider adding:
- Prometheus for metrics
- Grafana for dashboards
- Loki for log aggregation
@@ -402,6 +421,7 @@ Consider adding:
### Scaling
For production scaling:
- Use external PostgreSQL (managed service)
- Use external Redis/Valkey cluster
- Load balance multiple API instances

View File

@@ -68,30 +68,30 @@ docker compose up -d
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `TRAEFIK_MODE` | `none` | Traefik mode: `bundled`, `upstream`, or `none` |
| `TRAEFIK_ENABLE` | `false` | Enable Traefik labels on services |
| `MOSAIC_API_DOMAIN` | `api.mosaic.local` | Domain for API service |
| `MOSAIC_WEB_DOMAIN` | `mosaic.local` | Domain for Web service |
| `MOSAIC_AUTH_DOMAIN` | `auth.mosaic.local` | Domain for Authentik service |
| `TRAEFIK_NETWORK` | `traefik-public` | External Traefik network (upstream mode) |
| `TRAEFIK_TLS_ENABLED` | `true` | Enable TLS/HTTPS |
| `TRAEFIK_ACME_EMAIL` | - | Email for Let's Encrypt (production) |
| `TRAEFIK_CERTRESOLVER` | - | Cert resolver name (e.g., `letsencrypt`) |
| `TRAEFIK_DASHBOARD_ENABLED` | `true` | Enable Traefik dashboard (bundled mode) |
| `TRAEFIK_DASHBOARD_PORT` | `8080` | Dashboard port (bundled mode) |
| `TRAEFIK_ENTRYPOINT` | `websecure` | Traefik entrypoint (`web` or `websecure`) |
| `TRAEFIK_DOCKER_NETWORK` | `mosaic-public` | Docker network for Traefik routing |
| Variable | Default | Description |
| --------------------------- | ------------------- | ---------------------------------------------- |
| `TRAEFIK_MODE` | `none` | Traefik mode: `bundled`, `upstream`, or `none` |
| `TRAEFIK_ENABLE` | `false` | Enable Traefik labels on services |
| `MOSAIC_API_DOMAIN` | `api.mosaic.local` | Domain for API service |
| `MOSAIC_WEB_DOMAIN` | `mosaic.local` | Domain for Web service |
| `MOSAIC_AUTH_DOMAIN` | `auth.mosaic.local` | Domain for Authentik service |
| `TRAEFIK_NETWORK` | `traefik-public` | External Traefik network (upstream mode) |
| `TRAEFIK_TLS_ENABLED` | `true` | Enable TLS/HTTPS |
| `TRAEFIK_ACME_EMAIL` | - | Email for Let's Encrypt (production) |
| `TRAEFIK_CERTRESOLVER` | - | Cert resolver name (e.g., `letsencrypt`) |
| `TRAEFIK_DASHBOARD_ENABLED` | `true` | Enable Traefik dashboard (bundled mode) |
| `TRAEFIK_DASHBOARD_PORT` | `8080` | Dashboard port (bundled mode) |
| `TRAEFIK_ENTRYPOINT` | `websecure` | Traefik entrypoint (`web` or `websecure`) |
| `TRAEFIK_DOCKER_NETWORK` | `mosaic-public` | Docker network for Traefik routing |
### Docker Compose Profiles
| Profile | Description |
|---------|-------------|
| Profile | Description |
| ----------------- | --------------------------------- |
| `traefik-bundled` | Activates bundled Traefik service |
| `authentik` | Enables Authentik SSO services |
| `ollama` | Enables Ollama AI service |
| `full` | Enables all optional services |
| `authentik` | Enables Authentik SSO services |
| `ollama` | Enables Ollama AI service |
| `full` | Enables all optional services |
## Deployment Scenarios
@@ -131,6 +131,7 @@ MOSAIC_AUTH_DOMAIN=auth.example.com
```
**Prerequisites:**
1. DNS records pointing to your server
2. Ports 80 and 443 accessible from internet
3. Uncomment ACME configuration in `docker/traefik/traefik.yml`
@@ -216,6 +217,7 @@ services:
```
Generate basic auth password:
```bash
echo $(htpasswd -nb admin your-password) | sed -e s/\\$/\\$\\$/g
```
@@ -233,6 +235,7 @@ tls:
```
Mount certificate directory:
```yaml
# docker-compose.override.yml
services:
@@ -248,7 +251,6 @@ Route multiple domains to different services:
```yaml
# .env
MOSAIC_WEB_DOMAIN=mosaic.local,app.mosaic.local,www.mosaic.local
# Traefik will match all domains
```
@@ -271,11 +273,13 @@ services:
### Services Not Accessible via Domain
**Check Traefik is running:**
```bash
docker ps | grep traefik
```
**Check Traefik dashboard:**
```bash
# Bundled mode
open http://localhost:8080
@@ -285,11 +289,13 @@ curl http://localhost:8080/api/http/routers | jq
```
**Verify labels are applied:**
```bash
docker inspect mosaic-api | jq '.Config.Labels'
```
**Check DNS/hosts file:**
```bash
# Local development
cat /etc/hosts | grep mosaic
@@ -298,10 +304,12 @@ cat /etc/hosts | grep mosaic
### Certificate Errors
**Self-signed certificates (development):**
- Browser warnings are expected
- Add exception in browser or import CA certificate
**Let's Encrypt failures:**
```bash
# Check Traefik logs
docker logs mosaic-traefik
@@ -316,21 +324,25 @@ docker exec mosaic-traefik ls -la /letsencrypt/
### Upstream Mode Not Connecting
**Verify external network exists:**
```bash
docker network ls | grep traefik-public
```
**Create network if missing:**
```bash
docker network create traefik-public
```
**Check service network attachment:**
```bash
docker inspect mosaic-api | jq '.NetworkSettings.Networks'
```
**Verify external Traefik can see services:**
```bash
# From external Traefik container
docker exec <external-traefik-container> traefik healthcheck
@@ -339,6 +351,7 @@ docker exec <external-traefik-container> traefik healthcheck
### Port Conflicts
**Bundled mode port conflicts:**
```bash
# Check what's using ports
sudo lsof -i :80
@@ -354,17 +367,20 @@ TRAEFIK_DASHBOARD_PORT=8081
### Dashboard Not Accessible
**Check dashboard is enabled:**
```bash
# In .env
TRAEFIK_DASHBOARD_ENABLED=true
```
**Verify Traefik configuration:**
```bash
docker exec mosaic-traefik cat /etc/traefik/traefik.yml | grep -A5 "api:"
```
**Access dashboard:**
```bash
# Default
http://localhost:8080/dashboard/
@@ -389,11 +405,13 @@ http://localhost:${TRAEFIK_DASHBOARD_PORT}/dashboard/
### Securing the Dashboard
**Option 1: Disable in production**
```bash
TRAEFIK_DASHBOARD_ENABLED=false
```
**Option 2: Add basic authentication**
```yaml
# docker-compose.override.yml
services:
@@ -409,6 +427,7 @@ services:
```
**Option 3: IP whitelist**
```yaml
# docker-compose.override.yml
services: