Files
pulse/tests/integration/docker-compose.test.yml
T
rcourtman ee67141fa2 Add MSP isolation E2E spec: token scoping, split-port ingest, signed webhook delivery
Automates the docs/MSP.md validation checklist and the WEBHOOKS.md
delivery contract against the real server, covering the cross-layer
seams unit tests cannot see (today's two isolation bugs both lived
there):

- org-bound token allowed in its own org, denied 403 in sibling orgs
  AND the default org (leaked client-site token must not read the
  provider estate)
- dedicated agent-ingest port serves only /api/agents/* (management
  paths 404, agent route auth-gated)
- client-org webhook delivery through the instance-wide private-target
  allowlist saved in default-org context, with HMAC signature verified
  against the documented recipe, X-Pulse-Event-ID idempotency header,
  and tenant id/name stamped in the payload
- restart inheritance: after docker restart the persisted allowlist
  still applies to lazily recreated tenant monitors (skips when the
  docker CLI cannot manage the container)

Compose: pulse-test gains PULSE_AGENT_INGEST_PORT=7656 (+ port map)
and a host-gateway extra_host so the spec's capture listener is
reachable from the container.
2026-06-10 12:06:35 +01:00

88 lines
2.8 KiB
YAML

services:
# Seed a deterministic bootstrap token for first-run setup E2E flows.
# This is only used by the test stack and is safe to keep deterministic.
seed-bootstrap-token:
image: alpine:3.20
container_name: pulse-test-seed-bootstrap-token
environment:
- PULSE_E2E_BOOTSTRAP_TOKEN=${PULSE_E2E_BOOTSTRAP_TOKEN:-0123456789abcdef0123456789abcdef0123456789abcdef}
volumes:
- test-data:/data
command: >
sh -c "set -e; umask 077; echo \"$$PULSE_E2E_BOOTSTRAP_TOKEN\" > /data/.bootstrap_token"
networks:
- test-network
# Mock GitHub API server for controlled testing
mock-github:
image: pulse-mock-github:test
container_name: pulse-mock-github
ports:
- "${PULSE_E2E_MOCK_GITHUB_PORT:-8080}:8080"
environment:
- PORT=8080
- MOCK_BASE_URL=http://mock-github:8080
# Control test scenarios via environment variables
- MOCK_CHECKSUM_ERROR=${MOCK_CHECKSUM_ERROR:-false}
- MOCK_NETWORK_ERROR=${MOCK_NETWORK_ERROR:-false}
- MOCK_RATE_LIMIT=${MOCK_RATE_LIMIT:-false}
- MOCK_STALE_RELEASE=${MOCK_STALE_RELEASE:-false}
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 5s
timeout: 3s
retries: 3
start_period: 5s
networks:
- test-network
# Pulse server under test
pulse-test:
image: pulse:test
container_name: pulse-test-server
ports:
- "${PULSE_E2E_PORT:-7655}:7655"
- "${PULSE_E2E_AGENT_PORT:-7656}:7656"
environment:
- TZ=UTC
# Dedicated agent-ingest listener so E2E can prove the split-port
# isolation contract (only /api/agents/* served on this port).
- PULSE_AGENT_INGEST_PORT=7656
# Point to mock GitHub server
- PULSE_UPDATE_SERVER=http://mock-github:8080
# Use /data which is already owned by pulse user via entrypoint
- PULSE_DATA_DIR=/data
# Enable debug logging
- PULSE_LOG_LEVEL=debug
# Mock mode for faster testing
- PULSE_MOCK_MODE=true
- PULSE_MULTI_TENANT_ENABLED=${PULSE_MULTI_TENANT_ENABLED:-false}
- PULSE_ALLOW_DOCKER_UPDATES=true
- PULSE_UPDATE_STAGE_DELAY_MS=250
volumes:
- test-data:/data
extra_hosts:
# Lets webhook E2E point Pulse at a capture listener on the test host.
- "host.docker.internal:host-gateway"
depends_on:
seed-bootstrap-token:
condition: service_completed_successfully
mock-github:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:7655/api/health"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s
networks:
- test-network
volumes:
test-data:
driver: local
networks:
test-network:
driver: bridge