services:
  agap-mcp:
    build: .
    restart: unless-stopped
    network_mode: host
    environment:
      - PORT=3100
      - NODE_TLS_REJECT_UNAUTHORIZED=0
      - HTTPS_PROXY=
      - HTTP_PROXY=
      - ALL_PROXY=
      - https_proxy=
      - http_proxy=
      - all_proxy=
      - BITWARDENCLI_APPDATA_DIR=/bw-data
      - BW_EMAIL=adolf46@proton.me
      - BW_PASSWORD=${BW_PASSWORD}
      - VAULTWARDEN_URL=http://localhost:8041
      - GITEA_URL=http://localhost:3000
      - HA_URL=http://192.168.1.4:8123
      - ZABBIX_URL=http://192.168.1.4:81
      - RADICALE_URL=http://localhost:5232
      - RADICALE_USER=alvis
      # kb#147 (A2A-15) — vault trust gate, OFF by default (0). Flipping this
      # to 1 requires a container restart AND real values for
      # AGENT_REGISTRY_PATH/AGAP_MCP_AGENT_TOKENS below to be populated first
      # (see src/trust-gate.js) — that restart is the deliberate handover
      # step this task does NOT perform (never restart the live agap-mcp
      # service unattended). Until both are set, vw_* tools behave exactly
      # as before this change.
      - AGAP_MCP_ENFORCE_VAULT_TRUST=0
      - AGENT_REGISTRY_PATH=/agent-registry.yaml
      # JSON map {"<bearer-token>": "<agent-id>"}. Real per-agent tokens must
      # be generated, stored in Vaultwarden (e.g. AGAP_MCP_TOKEN_ADOLF,
      # AGAP_MCP_TOKEN_CLAUDE_CODER), and referenced here via .env — never
      # inlined in this committed file. Empty object = no caller resolves to
      # any agent, i.e. fail-closed once ENFORCE is turned on.
      - AGAP_MCP_AGENT_TOKENS=${AGAP_MCP_AGENT_TOKENS:-{}}
      # kb#180 (DESIGN-a2a-agents.md §4) — authentication of the LISTENER
      # itself, a strictly larger gate than the vw_*-only one above. With
      # this on (the default in code), /mcp, /sse, /messages and
      # /capture-idea all require `Authorization: Bearer <token>` resolving
      # to an agent id in AGAP_MCP_AGENT_TOKENS; /health stays open for this
      # healthcheck. :3100 is bound on every interface (network_mode: host)
      # and the LAN carries VPN-terminated peers, so an open listener means
      # any peer can call ha_call_service / gitea_wiki_write / wiki_edit /
      # todoist writes.
      #
      # ACTIVATION IS NOT AUTOMATIC-SAFE: with auth on and
      # AGAP_MCP_AGENT_TOKENS empty, the process REFUSES TO START (loud
      # crash instead of denying every caller while /health says ok). So
      # AGAP_MCP_AGENT_TOKENS must be populated in this directory's .env
      # BEFORE the next restart of this service, and every caller
      # (Adolf/shared-mcp.json, Claude Code .claude.json, the
      # todoist-capture-plugin) must be given its token — see the kb#180
      # migration list. Set AGAP_MCP_REQUIRE_AUTH=0 in .env only as a
      # deliberate emergency rollback to the old open listener.
      - AGAP_MCP_REQUIRE_AUTH=${AGAP_MCP_REQUIRE_AUTH:-1}
    volumes:
      - /home/alvis/.config/Bitwarden CLI:/bw-data
      # Read-only: agent-registry.yaml is the version-controlled source of
      # truth for trust classes (kb#134/kb#147) — mounted, never copied, so
      # a registry edit takes effect on container restart with no rebuild.
      - /home/alvis/agap_git/openai/agent-registry.yaml:/agent-registry.yaml:ro
    # kb#190: /health responds 200 with no auth/side effects (confirmed).
    # This is a SEPARATE compose project from openai/docker-compose.yml
    # (network_mode: host, reached from adolf-llm etc. via
    # host.docker.internal), so it cannot be wired into that file's
    # depends_on/condition chain -- this only gives it its own status.
    healthcheck:
      test: ["CMD-SHELL", "node -e \"fetch('http://localhost:3100/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""]
      interval: 15s
      timeout: 10s
      retries: 5
      start_period: 20s
