Collector Live Demo & Testing Guide
This guide describes how to test, demonstrate, and verify the CX Orbit Event Collector (apps/collector) during live presentations, audits, or QA.
1. Architectural Role in CX Orbit
In CX Orbit, the Collector is the sole external write ingress (ADR 0002):
- SDKs and external integrations never write directly to the database.
- The Collector validates incoming event batches, enforces authentication (
Authorization: Bearer <WRITE_KEY>), enforces schemas, quarantines malformed payloads, handles deduplication, and streams accepted canonical facts into storage. - It operates on port 8080 by default (local) or via
$COLLECTOR_PUBLIC_URLon staging/production.
2. Quick Verification (1-Command Demo)
To run the automated 5-step test suite live with colored terminal output:
./scripts/demo-collector.sh
This script automatically verifies:
- Service handshake (
GET /health) - Invalidation & quarantine (
POST /v1/events:batch→ENVIRONMENT_MISMATCH) - Valid authoritative ingestion (
POST /v1/events:batch→ACCEPTED) - Idempotency & deduplication (Re-send →
DUPLICATE_EVENT_ID) - Real-time metrics & debug fact inspection (
GET /metrics,GET /v1/debug/store)
3. Step-by-Step Manual Demo Script
Use these exact commands when walking through a live interactive terminal demonstration.
Step 1: Service Health Handshake
Command:
curl -s http://localhost:8080/health | jq .
Expected Response (HTTP 200):
{
"status": "ok",
"service": "cx-orbit-collector",
"environment": "development",
"project_id": "simiaroom",
"collector_version": "0.1.0"
}
Talking Point: "The collector is lightweight (Hono + TypeScript), isolated from the UI, and acts as the secure gatekeeper for all telemetry and domain events across Simiaroom."
Step 2: Schema & Environment Guardrail (Quarantine)
Demonstrate that invalid or mismatched data never silently corrupts the analytical store.
Command:
curl -s -X POST http://localhost:8080/v1/events:batch \
-H "Authorization: Bearer change-me-local-server-key" \
-H "Content-Type: application/json" \
-d '{
"events": [{
"event_id": "c03264cf-dc45-429a-8b89-40c2132d1694",
"event_version": 1,
"project_id": "simiaroom",
"environment": "production",
"source": "simiaroom_payments",
"source_event_id": "pay_test_err_01",
"sent_at": "2026-09-12T06:00:00Z",
"occurred_at": "2026-09-12T06:00:00Z",
"journey_ref": "J-05",
"canonical_type": "payment_succeeded",
"event_name": "payment_succeeded",
"identity": { "user_id": "usr_demo", "anonymous_id": null, "session_id": null },
"actor": { "type": "system", "id": "payment-gateway" },
"entity": { "type": "payment", "id": "pay_01" },
"properties": {
"order_id": "ord_01",
"booking_id": "bkg_01",
"package_id": "pkg_01",
"amount": 2500000,
"currency": "IRR",
"gateway": "zarinpal"
}
}]
}' | jq .
Expected Response (HTTP 422):
{
"status": "rejected",
"request_id": "ing_...",
"accepted": 0,
"rejected": 1,
"quarantined": 1,
"results": [{
"outcome": "quarantined",
"code": "ENVIRONMENT_MISMATCH",
"message": "environment must match collector environment (development)"
}]
}
Talking Point: "The collector rejected a production-tagged event sent to the development environment. It generated an audit quarantine record (
quarantine_id) without failing the caller or dropping data."
Step 3: Authoritative Event Ingestion (Success)
Demonstrate ingesting a valid business outcome event (e.g. payment_succeeded).
Command:
EVENT_UUID=$(uuidgen | tr '[:upper:]' '[:lower:]')
curl -s -X POST http://localhost:8080/v1/events:batch \
-H "Authorization: Bearer change-me-local-server-key" \
-H "Content-Type: application/json" \
-d '{
"events": [{
"event_id": "'"${EVENT_UUID}"'",
"event_version": 1,
"project_id": "simiaroom",
"environment": "development",
"source": "simiaroom_payments",
"source_event_id": "pay_demo_success_'$(date +%s)'",
"sent_at": "2026-09-12T06:00:00Z",
"occurred_at": "2026-09-12T06:00:00Z",
"journey_ref": "J-05",
"canonical_type": "payment_succeeded",
"event_name": "payment_succeeded",
"identity": { "user_id": "usr_demo", "anonymous_id": null, "session_id": null },
"actor": { "type": "system", "id": "payment-gateway" },
"entity": { "type": "payment", "id": "pay_success" },
"properties": {
"order_id": "ord_100",
"booking_id": "bkg_100",
"package_id": "pkg_12",
"amount": 2500000,
"currency": "IRR",
"gateway": "zarinpal"
}
}]
}' | jq .
Expected Response (HTTP 200):
{
"status": "ok",
"accepted": 1,
"duplicate": 0,
"rejected": 0,
"quarantined": 0,
"results": [{
"outcome": "accepted",
"code": "ACCEPTED"
}]
}
Talking Point: "The event is validated against strict Zod and JSON Schemas, validated for privacy (zero raw clinical text permitted), and committed as an immutable fact."
Step 4: Idempotency & Deduplication Proof
Re-send the exact same payload from Step 3 using the same EVENT_UUID.
Expected Response (HTTP 200):
{
"status": "ok",
"accepted": 0,
"duplicate": 1,
"rejected": 0,
"quarantined": 0,
"results": [{
"outcome": "duplicate",
"code": "DUPLICATE_EVENT_ID",
"message": "Already ingested; canonical fact unchanged"
}]
}
Talking Point: "If network retries, timeout recoveries, or producer replays occur, CX Orbit recognizes identical event IDs (
project_id + source + source_event_id). It acknowledges receipt safely without double-counting metrics."
Step 5: Real-Time Observability & Health
Inspect pipeline metrics and the canonical debug store:
1. Live Metrics Counter:
curl -s http://localhost:8080/metrics | jq .
Shows sub-millisecond latencies, accepted batches, duplicate counts, and quarantine stats.
2. Storage Key References:
curl -s -H "Authorization: Bearer change-me-local-server-key" http://localhost:8080/v1/debug/store | jq .
Shows raw event count, canonical count, and registered event keys.
3. Web UI Alignment: Open http://localhost:3000/dq to view the live Data Health dashboard, where pipeline metrics, lag, and rejection rates update in real time.
4. Starting and Stopping Services
- Start collector in dev mode:
pnpm --filter @cx-orbit/collector dev - Run all unit tests for collector:
pnpm --filter @cx-orbit/collector test - Run TypeScript typecheck:
pnpm --filter @cx-orbit/collector typecheck