# docker-compose.yml — Cerbero Bite
#
# Bite runs in its own Compose project but joins the same Docker
# network used by Cerbero MCP V2 and Traefik (`traefik`) so it can
# either resolve the in-cluster service name (`cerbero-mcp:9000`)
# or reach the public gateway (`https://cerbero-mcp.tielogic.xyz`)
# transparently.
#
# The reverse-proxy network (`traefik`) is declared as external
# here. It is created by the Traefik stack at /opt/docker/traefik
# and shared by every web-facing service on the host.
#
# Authentication: a single bearer token is passed through from the
# host `.env` file via `CERBERO_BITE_MCP_TOKEN`. The Cerbero MCP V2
# server uses the token to decide whether the upstream environment
# is testnet or mainnet; switching environment = switching token.
#
# Two services are defined:
#   * `cerbero-bite`     — the trading engine / CLI worker
#   * `cerbero-bite-gui` — the Streamlit dashboard, exposed by
#                          Traefik at https://cerbero-bite.<DOMAIN>

networks:
  traefik:
    external: true

volumes:
  bite-data:

x-bite-env: &bite-env
  CERBERO_BITE_MCP_TOKEN: ${CERBERO_BITE_MCP_TOKEN:?missing CERBERO_BITE_MCP_TOKEN}
  CERBERO_BITE_MCP_BOT_TAG: ${CERBERO_BITE_MCP_BOT_TAG:-BOT__CERBERO_BITE}
  # Two independent runtime flags that decide what each cycle does.
  # Initial period ("data-only"): DATA_ANALYSIS=true, STRATEGY=false.
  CERBERO_BITE_ENABLE_DATA_ANALYSIS: ${CERBERO_BITE_ENABLE_DATA_ANALYSIS:-true}
  CERBERO_BITE_ENABLE_STRATEGY: ${CERBERO_BITE_ENABLE_STRATEGY:-false}
  # Service URLs — defaults below match the in-cluster Traefik network
  # DNS (V2 unified image listening on port 9000). Override any of
  # them via .env to point at the public gateway, a custom host, or
  # localhost for dev work.
  CERBERO_BITE_MCP_DERIBIT_URL: ${CERBERO_BITE_MCP_DERIBIT_URL:-http://cerbero-mcp:9000/mcp-deribit}
  CERBERO_BITE_MCP_HYPERLIQUID_URL: ${CERBERO_BITE_MCP_HYPERLIQUID_URL:-http://cerbero-mcp:9000/mcp-hyperliquid}
  CERBERO_BITE_MCP_MACRO_URL: ${CERBERO_BITE_MCP_MACRO_URL:-http://cerbero-mcp:9000/mcp-macro}
  CERBERO_BITE_MCP_SENTIMENT_URL: ${CERBERO_BITE_MCP_SENTIMENT_URL:-http://cerbero-mcp:9000/mcp-sentiment}

services:
  cerbero-bite:
    build:
      context: .
      dockerfile: Dockerfile
    image: cerbero-bite:dev
    restart: unless-stopped
    networks: [traefik]
    cap_drop: [ALL]
    security_opt:
      - no-new-privileges:true
    environment:
      <<: *bite-env
      # Telegram and Portfolio are no longer shared MCP services. The
      # bot now calls the Telegram Bot API directly and aggregates
      # portfolio in-process from Deribit + Hyperliquid + Macro.
      # Set the two env vars below to enable Telegram notifications.
      # CERBERO_BITE_TELEGRAM_BOT_TOKEN: ...
      # CERBERO_BITE_TELEGRAM_CHAT_ID: ...
    volumes:
      - bite-data:/app/data
    healthcheck:
      test:
        ["CMD", "cerbero-bite", "healthcheck", "--db", "/app/data/state.sqlite"]
      interval: 60s
      timeout: 5s
      retries: 3
      start_period: 120s
    # Engine main loop (scheduler + monitoring). Switch to `status`,
    # `ping`, `dry-run`, ... for one-shot diagnostics. The MCP token in
    # `.env` decides the upstream environment server-side; the `start`
    # flag below tells the local boot check what to expect (must match,
    # otherwise the engine arms the kill switch).
    command: ["start", "--environment", "mainnet"]

  # Streamlit dashboard published by Traefik on
  # https://cerbero-bite.${DOMAIN_NAME:-tielogic.xyz}
  #
  # The CLI sub-command `cerbero-bite gui` hard-codes the listen
  # address to 127.0.0.1, so we bypass the entrypoint and invoke
  # Streamlit directly. The two `CERBERO_BITE_GUI_*` env vars match
  # what the CLI normally injects (see src/cerbero_bite/cli.py).
  cerbero-bite-gui:
    image: cerbero-bite:dev
    restart: unless-stopped
    depends_on:
      - cerbero-bite
    networks: [traefik]
    cap_drop: [ALL]
    security_opt:
      - no-new-privileges:true
    environment:
      <<: *bite-env
      CERBERO_BITE_GUI_DB: /app/data/state.sqlite
      CERBERO_BITE_GUI_AUDIT: /app/data/log/audit.jsonl
    volumes:
      - bite-data:/app/data
    entrypoint:
      - python
      - -m
      - streamlit
      - run
      - /app/src/cerbero_bite/gui/main.py
      - --server.address=0.0.0.0
      - --server.port=8765
      - --server.headless=true
      - --browser.gatherUsageStats=false
    command: []
    healthcheck:
      test:
        - "CMD"
        - "python"
        - "-c"
        - "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8765/_stcore/health', timeout=3).close()"
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 30s
    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik
      - "traefik.http.routers.cerbero-bite.rule=Host(`cerbero-bite.${DOMAIN_NAME:-tielogic.xyz}`)"
      - traefik.http.routers.cerbero-bite.tls=true
      - traefik.http.routers.cerbero-bite.entrypoints=websecure
      - traefik.http.routers.cerbero-bite.tls.certresolver=mytlschallenge
      - traefik.http.services.cerbero-bite.loadbalancer.server.port=8765
      - com.centurylinklabs.watchtower.enable=true
