exocortex-cluster 0.4.0

Exocortex cluster coherence: Chubby-style leases with epoch fencing, HMAC-signed invalidation envelopes, and the SSE change feed.
# M5 harness: a FalkorDB instance shared by the three exocortex-node
# replicas (falkordb IS the redis coherence layer, ยง9.1 principle 6).
# CI starts the nodes with:
#   docker compose -f docker-compose-cluster.yml up -d falkordb
#   FALKOR_URL=falkor://127.0.0.1:16379 cargo test -p exocortex-cluster --features integration
services:
  falkordb:
    image: falkordb/falkordb@sha256:adbddd418916c25618564ff8597a919b08bc76452ebeb74eb985c38d7281df62
    ports:
      - "127.0.0.1:16379:6379"
    healthcheck:
      test: ["CMD", "redis-cli", "PING"]
      interval: 1s
      timeout: 3s
      retries: 30
  policy-init:
    image: busybox:1.36.1-musl@sha256:3c6ae8008e2c2eedd141725c30b20d9c36b026eb796688f88205845ef17aa213
    command: ["sh", "-c", "install -m 0600 -o 65532 -g 65532 /input/principal-policy.json /output/principal-policy.json && install -m 0600 -o 65532 -g 65532 /input/source-policy.json /output/source-policy.json"]
    volumes: ["./principal-policy.dev.json:/input/principal-policy.json:ro", "./source-policy.empty.json:/input/source-policy.json:ro", "policy-data:/output"]
  node1:
    image: exocortex-node:local
    build:
      context: ../../..
      dockerfile: Dockerfile
    depends_on:
      falkordb:
        condition: service_healthy
      policy-init:
        condition: service_completed_successfully
    environment:
      EXOCORTEX_CLUSTER_SECRET: "4242424242424242424242424242424242424242424242424242424242424242"
      EXOCORTEX_CHAOS_DREAMS_BARRIER_KEY: "exocortex:chaos:dreams-r6"
    command: ["--mode", "backend-node", "--bind", "0.0.0.0:8081", "--tls-cert", "/etc/exocortex/tls-cert.pem", "--tls-key", "/etc/exocortex/tls-key.pem", "--node-id", "node1", "--gossip-addr", "0.0.0.0:8101", "--principal-policy", "/run/exocortex-policies/principal-policy.json", "--source-policy", "/run/exocortex-policies/source-policy.json", "--storage", "falkor://falkordb:6379", "--allow-private-network-plaintext-data-plane", "--cluster-endpoints", "node2:8082,node3:8083"]
    volumes: ["policy-data:/run/exocortex-policies:ro", "../../exocortex-server/tests/fixtures/localhost-cert.pem:/etc/exocortex/tls-cert.pem:ro", "../../exocortex-server/tests/fixtures/localhost-key.pem:/etc/exocortex/tls-key.pem:ro"]
    ports:
      - "127.0.0.1:8081:8081"
  node2:
    image: exocortex-node:local
    build:
      context: ../../..
      dockerfile: Dockerfile
    depends_on:
      falkordb:
        condition: service_healthy
      policy-init:
        condition: service_completed_successfully
    environment:
      EXOCORTEX_CLUSTER_SECRET: "4242424242424242424242424242424242424242424242424242424242424242"
      EXOCORTEX_CHAOS_DREAMS_BARRIER_KEY: "exocortex:chaos:dreams-r6"
    command: ["--mode", "backend-node", "--bind", "0.0.0.0:8082", "--tls-cert", "/etc/exocortex/tls-cert.pem", "--tls-key", "/etc/exocortex/tls-key.pem", "--node-id", "node2", "--gossip-addr", "0.0.0.0:8102", "--principal-policy", "/run/exocortex-policies/principal-policy.json", "--source-policy", "/run/exocortex-policies/source-policy.json", "--storage", "falkor://falkordb:6379", "--allow-private-network-plaintext-data-plane", "--cluster-endpoints", "node1:8081,node3:8083"]
    volumes: ["policy-data:/run/exocortex-policies:ro", "../../exocortex-server/tests/fixtures/localhost-cert.pem:/etc/exocortex/tls-cert.pem:ro", "../../exocortex-server/tests/fixtures/localhost-key.pem:/etc/exocortex/tls-key.pem:ro"]
    ports:
      - "127.0.0.1:8082:8082"
  node3:
    image: exocortex-node:local
    build:
      context: ../../..
      dockerfile: Dockerfile
    depends_on:
      falkordb:
        condition: service_healthy
      policy-init:
        condition: service_completed_successfully
    environment:
      EXOCORTEX_CLUSTER_SECRET: "4242424242424242424242424242424242424242424242424242424242424242"
      EXOCORTEX_CHAOS_DREAMS_BARRIER_KEY: "exocortex:chaos:dreams-r6"
    command: ["--mode", "backend-node", "--bind", "0.0.0.0:8083", "--tls-cert", "/etc/exocortex/tls-cert.pem", "--tls-key", "/etc/exocortex/tls-key.pem", "--node-id", "node3", "--gossip-addr", "0.0.0.0:8103", "--principal-policy", "/run/exocortex-policies/principal-policy.json", "--source-policy", "/run/exocortex-policies/source-policy.json", "--storage", "falkor://falkordb:6379", "--allow-private-network-plaintext-data-plane", "--cluster-endpoints", "node1:8081,node2:8082"]
    volumes: ["policy-data:/run/exocortex-policies:ro", "../../exocortex-server/tests/fixtures/localhost-cert.pem:/etc/exocortex/tls-cert.pem:ro", "../../exocortex-server/tests/fixtures/localhost-key.pem:/etc/exocortex/tls-key.pem:ro"]
    ports:
      - "127.0.0.1:8083:8083"

volumes:
  policy-data: