Skip to main content

Connection smoke test

A staged smoke test mirroring the console's "Test connection" flow (Integration bundle). Stages run in order and each reports what actually happened:

StageRequestPass condition
reachabilityGET /health200, status: ok, no failing checks. Abort on failure.
telemetry_subsystemGET /health/telemetry200 and healthy body.
topology_subsystemGET /health/topology200 and healthy body.
auth_topologyGET /topology?freshness_seconds=900 with x-api-key200; extract tenant_key, distinct node count, newest observed_at.

Stage 4 interpretation, matching the console: 401 means the key was rejected; 503 means the tenant data plane is unavailable (possibly a disabled tenant); 200 with zero nodes means authenticated but no telemetry in the last 15 minutes, so start the fleet agent; 200 with nodes means telemetry is flowing. With no key set, stages 1 to 3 still run and the auth stage is reported as not tested, never faked.

Set CONSTELLATION_API_BASE and optionally CONSTELLATION_API_TOKEN (common setup).

const BASE = (process.env.CONSTELLATION_API_BASE ?? 'https://api.constellation.space').replace(/\/$/, '')
const TOKEN = process.env.CONSTELLATION_API_TOKEN

type Stage = { stage: string; ok: boolean; detail: string; latencyMs: number }
const stages: Stage[] = []

type Health = { status?: string; checks?: Record<string, { ok?: boolean }> }
type Entity = { entity_id?: string; observed_at?: string; tags?: Record<string, string> }
type Topology = { tenant_key?: string; entities?: Entity[] }

async function probe(path: string, headers?: Record<string, string>) {
const started = Date.now()
try {
const res = await fetch(`${BASE}${path}`, { headers, signal: AbortSignal.timeout(8000) })
const json = await res.json().catch(() => null)
return { status: res.status, json, latencyMs: Date.now() - started, error: null as string | null }
} catch {
return { status: 0, json: null, latencyMs: Date.now() - started,
error: 'Network error or timeout. Check the base URL and egress.' }
}
}

function healthStage(name: string, label: string, r: Awaited<ReturnType<typeof probe>>) {
const body = r.json as Health | null
const failing = Object.entries(body?.checks ?? {}).filter(([, c]) => c.ok === false).map(([n]) => n)
const ok = r.error == null && r.status === 200 && body?.status === 'ok' && failing.length === 0
const detail = r.error ?? (ok ? `${label} healthy.` :
`${label} degraded (status ${r.status}${failing.length ? `, failing: ${failing.join(', ')}` : ''}).`)
stages.push({ stage: name, ok, detail, latencyMs: r.latencyMs })
return ok
}

// Stage 1: reachability. Abort if the platform itself is down.
if (!healthStage('reachability', 'Platform API', await probe('/health'))) {
report()
process.exit(2)
}

// Stages 2 and 3: subsystems.
healthStage('telemetry_subsystem', 'Telemetry subsystem', await probe('/health/telemetry'))
healthStage('topology_subsystem', 'Topology subsystem', await probe('/health/topology'))

// Stage 4: authenticated data plane.
if (TOKEN) {
const r = await probe('/topology?freshness_seconds=900', { 'x-api-key': TOKEN })
if (r.error) {
stages.push({ stage: 'auth_topology', ok: false, detail: r.error, latencyMs: r.latencyMs })
} else if (r.status === 401) {
stages.push({ stage: 'auth_topology', ok: false,
detail: 'API key rejected (401). Verify the tenant x-api-key.', latencyMs: r.latencyMs })
} else if (r.status === 503) {
stages.push({ stage: 'auth_topology', ok: false,
detail: 'Tenant data plane unavailable (503). The tenant may be disabled.', latencyMs: r.latencyMs })
} else if (r.status !== 200) {
stages.push({ stage: 'auth_topology', ok: false,
detail: `Unexpected status ${r.status}.`, latencyMs: r.latencyMs })
} else {
const topo = r.json as Topology
const nodes = new Set((topo.entities ?? []).map((e) => e.tags?.node_id ?? e.entity_id).filter(Boolean))
const newest = (topo.entities ?? []).map((e) => e.observed_at ?? '').sort().at(-1) || null
stages.push({ stage: 'auth_topology', ok: true, latencyMs: r.latencyMs,
detail: nodes.size > 0
? `API key accepted (tenant ${topo.tenant_key}). Telemetry flowing: ${nodes.size} nodes, newest sample ${newest}.`
: `API key accepted (tenant ${topo.tenant_key}), but no telemetry in the last 15 minutes. Start the fleet agent to begin ingest.` })
}
} else {
console.log('note: CONSTELLATION_API_TOKEN not set; authenticated stage not tested')
}

function report() {
for (const s of stages) {
console.log(`${s.ok ? 'PASS' : 'FAIL'} ${s.stage.padEnd(20)} ${s.latencyMs}ms ${s.detail}`)
}
}
report()
process.exit(stages.every((s) => s.ok) ? 0 : 1)

Expected output for a fully connected tenant:

PASS reachability 112ms Platform API healthy.
PASS telemetry_subsystem 148ms Telemetry subsystem healthy.
PASS topology_subsystem 139ms Topology subsystem healthy.
PASS auth_topology 201ms API key accepted (tenant acme-sat). Telemetry flowing: 24 nodes, newest sample 2026-07-09T14:31:55Z.