Excititor Consensus Removal Runbook (AOC-19-004)

Audience: Operators and platform engineers running a cutover that removes legacy consensus/merged-severity data from Excititor. Goal: Eliminate legacy consensus and merged-severity fields so Excititor remains aggregation-only — raw VEX observations and linksets in, no derived verdicts. Severity merging and policy evaluation move to the Policy Engine.

For the aggregation guardrails this cutover enforces, see the Excititor architecture dossier.

Cutover steps

  1. Freeze consensus refreshDisableConsensus=true (default) forces refresh loop off. Keep this enabled during migration.
  2. Schema cleanup — migrate collections to remove or null legacy fields:
    • vex_consensus / vex_consensus_holds: drop/ignore fields consensusDigest, policyVersion, policyRevisionId, policyDigest, summary, signals, status (merged) once Policy takes over.
    • vex_observations / materialized exports: ensure no merged severity/status fields are written.
    • vex_mirror exports: stop emitting consensus JSON; retain raw observations only.
  3. Telemetry: emit counter excititor.ingest.consensus.disabled (tags tenant, source, connectorId) once per batch to prove cutover.
  4. Guards: AOC guards reject any incoming/derived field in {mergedSeverity, consensusScore, computedStatus}.
  5. Backfill: run one-off job to set consensusDisabled=true on legacy records and remove merged fields without touching raw observations.
  6. Verification: regression checklist (per tenant):
    • No writes to vex_consensus* collections after cutover.
    • Ingest + export fixtures show only raw observations/linksets; snapshots deterministic.
    • Telemetry counter present; absence of consensus refresh logs.

Config

Excititor:Worker:
  DisableConsensus: true   # keep true post-cutover

Test plan