StellaOps Excititor (absorbed into the Concelier domain — Sprint 203)

Status: Excititor source code now lives under src/Concelier/StellaOps.Excititor.* following the advisory-domain consolidation (Sprint 203, 2026-03-04). This page is retained as the canonical Excititor reference and redirect; the full historical archive is at docs-archive/modules/excititor/, and the ADR is recorded in ../concelier/architecture.md.

Excititor is the StellaOps VEX aggregation service. It converts heterogeneous VEX feeds (OpenVEX, CSAF, CycloneDX) into raw, provenance-tagged observations and append-only linksets that honour the Aggregation-Only Contract (AOC). It is strictly aggregation-only: it stores and serves raw observations and linksets and does not compute consensus, merged severity, or derived status — those concerns moved to the Policy Engine / VEX Lens (see “Aggregation-only posture” below).

Audience: operators wiring VEX connectors and offline mirrors, and integrators consuming Excititor observations, linksets, the Risk-Engine feed, or the VEX evidence/chunk APIs.

Latest updates (verified 2026-05-30)

Aggregation-only posture (orphaned consensus content corrected, 2026-05-30): Earlier revisions of this README promoted an “Excititor consensus beta” and pointed at docs/vex/consensus-json.md, weighting knobs, and DSSE consensus-bundle packaging. Consensus computation was removed from Excititor under EXCITITOR-CORE-AOC-19-004 (see operations/consensus-removal-runbook.md). The Worker ships with DisableConsensus=true and AOC guards reject any derived field (mergedSeverity, consensusScore, computedStatus). Treat any remaining consensus references in this module’s history as superseded; consensus now lives in Policy / VEX Lens.

Release references

Responsibilities

Key components

Connectors

Seven VEX providers are wired (canonical IDs use the excititor: prefix). RedHat, Ubuntu, Oracle, and Cisco are seeded at runtime startup; SUSE Rancher, OCI OpenVEX, and MSRC are seeded by the consolidated baseline 001_v1_excititor_baseline.sql (provider-seed block at lines 865-885, folded in from the pre-1.0 008_seed_csaf_providers.sql); msrc and oci-openvex ship enabled=false:

Provider IDKindConnector library
excititor:redhatvendor (CSAF)StellaOps.Excititor.Connectors.RedHat.CSAF
excititor:ubuntuvendor (CSAF)StellaOps.Excititor.Connectors.Ubuntu.CSAF
excititor:oraclevendor (CSAF)StellaOps.Excititor.Connectors.Oracle.CSAF
excititor:ciscovendor (CSAF)StellaOps.Excititor.Connectors.Cisco.CSAF
excititor:suse-rancherhubStellaOps.Excititor.Connectors.SUSE.RancherVEXHub
excititor:oci-openvexattestationStellaOps.Excititor.Connectors.OCI.OpenVEX.Attest
excititor:msrcvendor (CSAF)StellaOps.Excititor.Connectors.MSRC.CSAF

A StellaOps mirror connector (StellaOps.Excititor.Connectors.StellaOpsMirror) consumes mirror exports for air-gap re-ingest. Each connector binds from Excititor:Connectors:<Name> so air-gap operators can repoint URLs without code changes. Provider control-plane inventory and readiness notes: operations/provider-control-plane.md. Per-connector credentials: operations/provider-credentials.md. Ubuntu CSAF provenance knobs (TrustWeight/Tier, cosign, fingerprint): operations/ubuntu-csaf.md.

API surface & scopes

Routes are served by StellaOps.Excititor.WebService. Authorization is enforced by the gateway JWT bearer middleware plus per-endpoint scope checks. The canonical scope catalog (StellaOps.Auth.Abstractions.StellaOpsScopes) declares vex:read (VexRead), vex:ingest (VexIngest), and vex.admin (VexAdmin); the service additionally accepts the dotted aliases vex.read and vex.ingest, and uses vex.attest for Rekor attestation operations. Endpoints resolve the tenant from the X-StellaOps-TenantId header (falling back to the configured default tenant).

Route familyMethodsScopeNotes
/excititor/status, /excititor/healthGETanonymousService readiness / health
/obs/excititor/healthGETvex:readAuthenticated operational health; storage.connectionState distinguishes measured connected data from an unavailable degraded dependency
/.well-known/openapi, /openapi/excititor.jsonGETanonymousGenerated OpenAPI 3.1.1 discovery + runtime spec
/vex/observations, /vex/observations/{id}, /vex/observations/countGETvex.readRaw observations (no derived verdict fields)
/vex/linksets, /vex/linksets/{id}, /vex/linksets/lookup, /vex/linksets/count, /vex/linksets/conflictsGETvex.readAlias/product linksets + disagreement markers (ERR_AGG_* errors)
/excititor/init, /excititor/ingest/run, /excititor/ingest/resume, /excititor/reconcilePOSTvex.adminIngest control
/excititor/providers, …/{id}, …/enable, …/disable, …/run, …/configuration, …/artifactsGET/PUT/POST/DELETEvex.read (read) / vex.admin (mutate)Provider control plane
/excititor/resolve, /policy/v1/vex/lookupPOSTvex.readResolve / policy lookup
/excititor/mirror/domains/**GETanonymous (domain list/detail) / vex.read (index, export, download)Mirror distribution
/airgap/v1/vex/import, /airgap/v1/mirror/bundles/**POST/GETvex.admin (import) / vex.read (bundle queries)Sealed air-gap bundles
/evidence/vex/list, /evidence/vex/{bundleId}, /evidence/vex/locker/{bundleId}**, /v1/vex/evidence/chunksGETvex.readEvidence bundles / chunk API
/attestations/vex/list, /attestations/vex/{id}GETvex.readVEX attestation records (DSSE state)
/attestations/rekor/observations/{id}, …/batch, …/{id}/verify, /attestations/rekor/pending, /v1/attestations/verifyPOST/GETvex.attest (create) / vex.read (verify, pending)Rekor transparency attestation
/risk/v1/feed, /risk/v1/feed/item, /risk/v1/feed/by-advisory/{key}, /risk/v1/feed/by-artifact/**POST/GETvex.readRisk-Engine feed (no derived severity)
/v1/graph/status, /v1/graph/overlays, /v1/graph/observations, /internal/graph/linkoutsGET/POSTper-endpointGraph overlay surface
/aoc/verifyPOSTper-endpointAggregation-Only Contract verifier
/obs/excititor/timelineGET (SSE)vex.readTimeline event stream (X-Next-Cursor)

Detailed contracts: vex_observations.md, vex_linksets_api.md, api-reference.md, operations/evidence-api.md, operations/chunk-api-user-guide.md, and the pinned spec openapi/v1.json.

VEX status & justification values

VexClaimStatus (serialized): affected, not_affected, fixed, under_investigation. VexJustification carries the OpenVEX/CSAF justification vocabulary plus reachability-derived values (e.g. component_not_present, vulnerable_code_not_in_execute_path, code_not_reachable, protected_at_runtime). Linkset observation/disagreement rows constrain status to affected | not_affected | fixed | under_investigation.

Integrations & dependencies

Operational notes

Backlog references

Epic alignment

Implementation Status

Objectives

Key Milestones

Recent Delivery Status