version: "3.8" # Full-stack A2A Settlement ecosystem. # Run: docker compose up --build # # Services: # exchange — Core A2A Settlement Exchange (port 3000) # dashboard — Next.js admin dashboard (port 3001) # mediator — AI dispute mediator (port 3100) # shim — Security Shim / Economic Air Gap proxy (port 3300) # mcp — MCP tool server (port 3200, SSE) services: exchange: build: context: . dockerfile: Dockerfile ports: - "3000:3000" environment: A2A_EXCHANGE_HOST: "0.0.0.0" A2A_EXCHANGE_PORT: "3000" A2A_EXCHANGE_AUTO_CREATE_SCHEMA: "true" A2A_EXCHANGE_OPERATOR_API_KEY: "${A2A_OPERATOR_API_KEY:-ate_operator_dev_key}" A2A_EXCHANGE_DASHBOARD_API_KEY: "${A2A_DASHBOARD_API_KEY:-dashboard_dev_key}" A2A_EXCHANGE_KYA_ENABLED: "false" A2A_EXCHANGE_COMPLIANCE_ENABLED: "${A2A_COMPLIANCE_ENABLED:-false}" # Optional: enable settlement auth # A2A_EXCHANGE_SETTLEMENT_AUTH_ENABLED: "true" # A2A_EXCHANGE_SETTLEMENT_AUTH_KEY: "your-jwt-secret" volumes: - exchange-data:/app/data healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:3000/health')"] interval: 10s timeout: 5s retries: 3 dashboard: build: context: ../a2a-settlement-dashboard dockerfile: Dockerfile ports: - "3001:3000" environment: NEXT_PUBLIC_EXCHANGE_URL: "http://exchange:3000" NEXT_PUBLIC_DASHBOARD_API_KEY: "${A2A_DASHBOARD_API_KEY:-dashboard_dev_key}" NEXT_PUBLIC_USE_MOCK: "false" depends_on: exchange: condition: service_healthy mediator: build: context: ../a2a-settlement-mediator dockerfile: Dockerfile ports: - "3100:3100" environment: A2A_EXCHANGE_URL: "http://exchange:3000/v1" A2A_OPERATOR_API_KEY: "${A2A_OPERATOR_API_KEY:-ate_operator_dev_key}" MEDIATOR_HOST: "0.0.0.0" MEDIATOR_PORT: "3100" MEDIATOR_LLM_MODEL: "${MEDIATOR_LLM_MODEL:-anthropic/claude-sonnet-4-20250514}" MEDIATOR_AUTO_RESOLVE_THRESHOLD: "0.80" MEDIATOR_AUDIT_LOG: "true" MEDIATOR_DB_PATH: "/app/data/mediator.db" volumes: - mediator-data:/app/data depends_on: exchange: condition: service_healthy shim: build: context: . dockerfile: Dockerfile.shim ports: - "3300:3300" environment: A2A_SHIM_HOST: "0.0.0.0" A2A_SHIM_PORT: "3300" A2A_EXCHANGE_URL: "http://exchange:3000" A2A_EXCHANGE_API_KEY: "${A2A_OPERATOR_API_KEY:-ate_operator_dev_key}" A2A_SHIM_VAULT_URL: "" A2A_SHIM_VAULT_API_KEY: "${A2A_SHIM_VAULT_API_KEY:-}" A2A_SHIM_DESTINATION_MODE: "${A2A_SHIM_DESTINATION_MODE:-allow}" A2A_SHIM_DESTINATION_LIST: "${A2A_SHIM_DESTINATION_LIST:-}" A2A_SHIM_DEFAULT_COST: "${A2A_SHIM_DEFAULT_COST:-1.0}" A2A_SHIM_MAX_REQUEST_SIZE: "${A2A_SHIM_MAX_REQUEST_SIZE:-1048576}" depends_on: exchange: condition: service_healthy healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:3300/health')"] interval: 10s timeout: 5s retries: 3 mcp: build: context: ../a2a-settlement-mcp dockerfile: Dockerfile ports: - "3200:3200" environment: A2A_EXCHANGE_URL: "http://exchange:3000" A2A_API_KEY: "${A2A_OPERATOR_API_KEY:-ate_operator_dev_key}" A2A_MCP_TRANSPORT: "sse" A2A_MCP_PORT: "3200" depends_on: exchange: condition: service_healthy postgres: image: postgres:16-alpine ports: - "127.0.0.1:5432:5432" environment: POSTGRES_USER: a2a POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-a2a} POSTGRES_DB: a2a_exchange volumes: - pgdata:/var/lib/postgresql/data restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U a2a"] interval: 10s timeout: 5s retries: 3 volumes: exchange-data: mediator-data: pgdata: