Integrate BACKBEAT SDK and resolve KACHING license validation

Major integrations and fixes:
- Added BACKBEAT SDK integration for P2P operation timing
- Implemented beat-aware status tracking for distributed operations
- Added Docker secrets support for secure license management
- Resolved KACHING license validation via HTTPS/TLS
- Updated docker-compose configuration for clean stack deployment
- Disabled rollback policies to prevent deployment failures
- Added license credential storage (CHORUS-DEV-MULTI-001)

Technical improvements:
- BACKBEAT P2P operation tracking with phase management
- Enhanced configuration system with file-based secrets
- Improved error handling for license validation
- Clean separation of KACHING and CHORUS deployment stacks

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-09-06 07:56:26 +10:00
parent 543ab216f9
commit 9bdcbe0447
4730 changed files with 1480093 additions and 1916 deletions

View File

@@ -2,17 +2,14 @@ version: "3.9"
services:
chorus:
build:
context: ..
dockerfile: docker/Dockerfile
image: chorus:latest
image: anthonyrawlins/chorus:backbeat-v2.0.1
# REQUIRED: License configuration (CHORUS will not start without this)
environment:
# CRITICAL: License configuration - REQUIRED for operation
- CHORUS_LICENSE_EMAIL=${CHORUS_LICENSE_EMAIL:?CHORUS_LICENSE_EMAIL is required}
- CHORUS_LICENSE_KEY=${CHORUS_LICENSE_KEY:?CHORUS_LICENSE_KEY is required}
- CHORUS_LICENSE_ID_FILE=/run/secrets/chorus_license_id
- CHORUS_CLUSTER_ID=${CHORUS_CLUSTER_ID:-docker-cluster}
- CHORUS_KACHING_URL=${CHORUS_KACHING_URL:-https://kaching.chorus.services/api}
# Agent configuration
- CHORUS_AGENT_ID=${CHORUS_AGENT_ID:-} # Auto-generated if not provided
@@ -26,22 +23,41 @@ services:
- CHORUS_P2P_PORT=9000
- CHORUS_BIND_ADDRESS=0.0.0.0
# AI configuration
# AI configuration - Provider selection
- CHORUS_AI_PROVIDER=${CHORUS_AI_PROVIDER:-resetdata}
# ResetData configuration (default provider)
- RESETDATA_BASE_URL=${RESETDATA_BASE_URL:-https://models.au-syd.resetdata.ai/v1}
- RESETDATA_API_KEY=${RESETDATA_API_KEY:?RESETDATA_API_KEY is required for resetdata provider}
- RESETDATA_MODEL=${RESETDATA_MODEL:-meta/llama-3.1-8b-instruct}
# Ollama configuration (alternative provider)
- OLLAMA_ENDPOINT=${OLLAMA_ENDPOINT:-http://host.docker.internal:11434}
- CHORUS_DEFAULT_MODEL=${CHORUS_DEFAULT_MODEL:-llama3.1:8b}
# Model configuration
- CHORUS_MODELS=${CHORUS_MODELS:-meta/llama-3.1-8b-instruct}
- CHORUS_DEFAULT_REASONING_MODEL=${CHORUS_DEFAULT_REASONING_MODEL:-meta/llama-3.1-8b-instruct}
# Logging configuration
- LOG_LEVEL=${LOG_LEVEL:-info}
- LOG_FORMAT=${LOG_FORMAT:-structured}
# BACKBEAT configuration
- CHORUS_BACKBEAT_ENABLED=${CHORUS_BACKBEAT_ENABLED:-true}
- CHORUS_BACKBEAT_CLUSTER_ID=${CHORUS_BACKBEAT_CLUSTER_ID:-chorus-production}
- CHORUS_BACKBEAT_AGENT_ID=${CHORUS_BACKBEAT_AGENT_ID:-} # Auto-generated from CHORUS_AGENT_ID
- CHORUS_BACKBEAT_NATS_URL=${CHORUS_BACKBEAT_NATS_URL:-nats://backbeat-nats:4222}
# Docker secrets for sensitive configuration
secrets:
- chorus_license_id
# Persistent data storage
volumes:
- chorus_data:/app/data
# Network ports
ports:
- "${CHORUS_API_PORT:-8080}:8080" # HTTP API
- "${CHORUS_HEALTH_PORT:-8081}:8081" # Health checks
- "${CHORUS_P2P_PORT:-9000}:9000" # P2P communication
# Container resource limits
@@ -51,7 +67,7 @@ services:
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
failure_action: pause
order: start-first
restart_policy:
condition: on-failure
@@ -66,10 +82,11 @@ services:
cpus: "0.1"
memory: 128M
placement:
preferences:
- spread: node.id
constraints:
- node.role == worker
- node.hostname != rosewood
preferences:
- spread: node.hostname
# CHORUS is internal-only, no Traefik labels needed
# Network configuration
networks:
@@ -95,16 +112,424 @@ services:
retries: 3
start_period: 10s
whoosh:
image: anthonyrawlins/whoosh:backbeat-v2.1.0
ports:
- target: 8080
published: 8800
protocol: tcp
mode: ingress
environment:
# Database configuration
WHOOSH_DATABASE_DB_HOST: postgres
WHOOSH_DATABASE_DB_PORT: 5432
WHOOSH_DATABASE_DB_NAME: whoosh
WHOOSH_DATABASE_DB_USER: whoosh
WHOOSH_DATABASE_DB_PASSWORD_FILE: /run/secrets/whoosh_db_password
WHOOSH_DATABASE_DB_SSL_MODE: disable
WHOOSH_DATABASE_DB_AUTO_MIGRATE: "true"
# Server configuration
WHOOSH_SERVER_LISTEN_ADDR: ":8080"
WHOOSH_SERVER_READ_TIMEOUT: "30s"
WHOOSH_SERVER_WRITE_TIMEOUT: "30s"
WHOOSH_SERVER_SHUTDOWN_TIMEOUT: "30s"
# GITEA configuration
WHOOSH_GITEA_BASE_URL: https://gitea.chorus.services
WHOOSH_GITEA_TOKEN_FILE: /run/secrets/gitea_token
WHOOSH_GITEA_WEBHOOK_TOKEN_FILE: /run/secrets/webhook_token
WHOOSH_GITEA_WEBHOOK_PATH: /webhooks/gitea
# Auth configuration
WHOOSH_AUTH_JWT_SECRET_FILE: /run/secrets/jwt_secret
WHOOSH_AUTH_SERVICE_TOKENS_FILE: /run/secrets/service_tokens
WHOOSH_AUTH_JWT_EXPIRY: "24h"
# Logging
WHOOSH_LOGGING_LEVEL: debug
WHOOSH_LOGGING_ENVIRONMENT: production
# Redis configuration
WHOOSH_REDIS_ENABLED: "true"
WHOOSH_REDIS_HOST: redis
WHOOSH_REDIS_PORT: 6379
WHOOSH_REDIS_PASSWORD_FILE: /run/secrets/redis_password
WHOOSH_REDIS_DATABASE: 0
secrets:
- whoosh_db_password
- gitea_token
- webhook_token
- jwt_secret
- service_tokens
- redis_password
deploy:
replicas: 2
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
update_config:
parallelism: 1
delay: 10s
failure_action: pause
monitor: 60s
order: start-first
# rollback_config:
# parallelism: 1
# delay: 0s
# failure_action: pause
# monitor: 60s
# order: stop-first
placement:
preferences:
- spread: node.hostname
resources:
limits:
memory: 256M
cpus: '0.5'
reservations:
memory: 128M
cpus: '0.25'
labels:
- traefik.enable=true
- traefik.http.routers.whoosh.rule=Host(`whoosh.chorus.services`)
- traefik.http.routers.whoosh.tls=true
- traefik.http.routers.whoosh.tls.certresolver=letsencrypt
- traefik.http.services.whoosh.loadbalancer.server.port=8080
- traefik.http.middlewares.whoosh-auth.basicauth.users=admin:$$2y$$10$$example_hash
networks:
- tengig
- whoosh-backend
- chorus_net
healthcheck:
test: ["CMD", "/app/whoosh", "--health-check"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: whoosh
POSTGRES_USER: whoosh
POSTGRES_PASSWORD_FILE: /run/secrets/whoosh_db_password
POSTGRES_INITDB_ARGS: --auth-host=scram-sha-256
secrets:
- whoosh_db_password
volumes:
- whoosh_postgres_data:/var/lib/postgresql/data
deploy:
replicas: 1
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
placement:
preferences:
- spread: node.hostname
resources:
limits:
memory: 512M
cpus: '1.0'
reservations:
memory: 256M
cpus: '0.5'
networks:
- whoosh-backend
- chorus_net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U whoosh"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
redis:
image: redis:7-alpine
command: sh -c 'redis-server --requirepass "$$(cat /run/secrets/redis_password)" --appendonly yes'
secrets:
- redis_password
volumes:
- whoosh_redis_data:/data
deploy:
replicas: 1
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
placement:
preferences:
- spread: node.hostname
resources:
limits:
memory: 128M
cpus: '0.25'
reservations:
memory: 64M
cpus: '0.1'
networks:
- whoosh-backend
- chorus_net
healthcheck:
test: ["CMD", "sh", "-c", "redis-cli --no-auth-warning -a $$(cat /run/secrets/redis_password) ping"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
# BACKBEAT Pulse Service - Leader-elected tempo broadcaster
# REQ: BACKBEAT-REQ-001 - Single BeatFrame publisher per cluster
# REQ: BACKBEAT-OPS-001 - One replica prefers leadership
backbeat-pulse:
image: anthonyrawlins/backbeat-pulse:v1.0.5
command: >
./pulse
-cluster=chorus-production
-admin-port=8080
-raft-bind=0.0.0.0:9000
-data-dir=/data
-nats=nats://backbeat-nats:4222
-tempo=2
-bar-length=8
-log-level=info
# Internal service ports (not externally exposed - routed via Traefik)
expose:
- "8080" # Admin API
- "9000" # Raft communication
# REQ: BACKBEAT-OPS-002 - Health probes for liveness/readiness
healthcheck:
test: ["CMD", "nc", "-z", "localhost", "8080"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
deploy:
replicas: 1 # Single leader with automatic failover
restart_policy:
condition: on-failure
delay: 30s # Wait longer for NATS to be ready
max_attempts: 5
window: 120s
update_config:
parallelism: 1
delay: 30s # Wait for leader election
failure_action: pause
monitor: 60s
order: start-first
placement:
preferences:
- spread: node.hostname
constraints:
- node.hostname != rosewood # Avoid intermittent gaming PC
resources:
limits:
memory: 256M
cpus: '0.5'
reservations:
memory: 128M
cpus: '0.25'
# Traefik routing for admin API
labels:
- traefik.enable=true
- traefik.http.routers.backbeat-pulse.rule=Host(`backbeat-pulse.chorus.services`)
- traefik.http.routers.backbeat-pulse.tls=true
- traefik.http.routers.backbeat-pulse.tls.certresolver=letsencryptresolver
- traefik.http.services.backbeat-pulse.loadbalancer.server.port=8080
networks:
- chorus_net
- tengig # External network for Traefik
# Container logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
tag: "backbeat-pulse/{{.Name}}/{{.ID}}"
# BACKBEAT Reverb Service - StatusClaim aggregator
# REQ: BACKBEAT-REQ-020 - Subscribe to INT-B and group by window_id
# REQ: BACKBEAT-OPS-001 - Reverb can scale stateless
backbeat-reverb:
image: anthonyrawlins/backbeat-reverb:v1.0.2
command: >
./reverb
-cluster=chorus-production
-nats=nats://backbeat-nats:4222
-bar-length=8
-log-level=info
# Internal service ports (not externally exposed - routed via Traefik)
expose:
- "8080" # Admin API
# REQ: BACKBEAT-OPS-002 - Health probes for orchestration (temporarily disabled for testing)
# healthcheck:
# test: ["CMD", "nc", "-z", "localhost", "8080"]
# interval: 30s
# timeout: 10s
# retries: 3
# start_period: 60s
deploy:
replicas: 2 # Stateless, can scale horizontally
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
update_config:
parallelism: 1
delay: 15s
failure_action: pause
monitor: 45s
order: start-first
placement:
preferences:
- spread: node.hostname
constraints:
- node.hostname != rosewood
resources:
limits:
memory: 512M # Larger for window aggregation
cpus: '1.0'
reservations:
memory: 256M
cpus: '0.5'
# Traefik routing for admin API
labels:
- traefik.enable=true
- traefik.http.routers.backbeat-reverb.rule=Host(`backbeat-reverb.chorus.services`)
- traefik.http.routers.backbeat-reverb.tls=true
- traefik.http.routers.backbeat-reverb.tls.certresolver=letsencryptresolver
- traefik.http.services.backbeat-reverb.loadbalancer.server.port=8080
networks:
- chorus_net
- tengig # External network for Traefik
# Container logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
tag: "backbeat-reverb/{{.Name}}/{{.ID}}"
# NATS Message Broker - Use existing or deploy dedicated instance
# REQ: BACKBEAT-INT-001 - Topics via NATS for at-least-once delivery
backbeat-nats:
image: nats:2.9-alpine
command: ["--jetstream"]
deploy:
replicas: 1
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
preferences:
- spread: node.hostname
constraints:
- node.hostname != rosewood
resources:
limits:
memory: 256M
cpus: '0.5'
reservations:
memory: 128M
cpus: '0.25'
networks:
- chorus_net
# Container logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
tag: "nats/{{.Name}}/{{.ID}}"
# KACHING services are deployed separately in their own stack
# License validation will access https://kaching.chorus.services/api
# Persistent volumes
volumes:
chorus_data:
driver: local
whoosh_postgres_data:
driver: local
driver_opts:
type: none
o: bind
device: /rust/containers/WHOOSH/postgres
whoosh_redis_data:
driver: local
driver_opts:
type: none
o: bind
device: /rust/containers/WHOOSH/redis
# Networks for CHORUS communication
networks:
tengig:
external: true
whoosh-backend:
driver: overlay
attachable: false
chorus_net:
driver: overlay
attachable: true
ipam:
config:
- subnet: 10.201.0.0/24
- subnet: 10.201.0.0/24
secrets:
chorus_license_id:
external: true
name: chorus_license_id
whoosh_db_password:
external: true
name: whoosh_db_password
gitea_token:
external: true
name: gitea_token
webhook_token:
external: true
name: whoosh_webhook_token
jwt_secret:
external: true
name: whoosh_jwt_secret
service_tokens:
external: true
name: whoosh_service_tokens
redis_password:
external: true
name: whoosh_redis_password