Skip to content

Event Flow

Events are the mechanism Vega uses to bridge the gap between a long-running background process (the scan) and the user-facing dashboard. Because scans can take minutes to run, the backend doesn't make the user wait for a single HTTP response — instead, it streams incremental updates as events.

How events work

flowchart LR
    Codex[Codex CLI subprocess]
    V16[v16 adapter\nv16/adapter.py]
    BackAdapter[Backend v16 adapter\napp/projects/v16_adapter.py]
    PS[ProjectService]
    EventStore[Event store\nPostgres or JSON]
    FindingStore[Finding store\nPostgres or JSON]
    API[Events API\n/v1/repositories/:id/events]
    UI[Dashboard\nLive scan feed]

    Codex -->|stdout JSON stream| V16
    V16 -->|V16Event objects| BackAdapter
    BackAdapter -->|mapped Vega events| PS
    PS -->|append| EventStore
    PS -->|upsert| FindingStore
    EventStore -->|GET events| API
    API -->|JSON array| UI

The two event stores

Events flow into two different places, depending on what they represent:

Event store — an append-only log of everything that happened during the scan. Used by the frontend for the live scan feed and by operators for debugging. Stored in app/events/service.py.

Finding store — durable security issues extracted from finding_updated events. These are structured records with severity, file path, and evidence. Stored and updated via ProjectService. The frontend shows these on the findings page after the scan finishes.

Event kinds

Kind What it means Stored as finding?
scan_started v16 has started running No
scan_progress Status update (e.g., component N of M) No
scan_log Debug log from v16 or Codex No
finding_updated A security issue was discovered or updated Yes
scan_completed All components audited, scan is done No
scan_failed v16 encountered an error No
scan_cancelled User or operator stopped the scan No

Why this design?

The event stream serves three purposes:

  1. Live UI — the frontend polls the events endpoint and shows a feed of what's happening right now.
  2. Debug log — after a scan finishes, operators can read the full event log to understand what Codex analyzed and what it found.
  3. Findings sourcefinding_updated events are the sole source of truth for security findings. The backend processes each one and upserts a finding record.

Debugging

If a scan appears to run but the UI doesn't update:

  1. Check that v16 actually emitted events — look at v16-events.jsonl in the scan artifacts.
  2. Check app/projects/v16_adapter.py — did it successfully map the raw v16 events?
  3. Check app/events/service.py — were events persisted to the store?
  4. Check the frontend — is it polling the right project/scan context, and are filters hiding events?

If events appear but no findings show up:

  1. Confirm v16 emitted finding_updated events (check v16-events.jsonl).
  2. Check ProjectService finding upsert logic in app/projects/service.py.
  3. If using Postgres, confirm migration 004_findings_columns.sql has been applied.
  4. Check the frontend findings page filters — severity or status filters might be hiding results.