Hummingbird Data Flow
Overview of all data sources, what is stored where, and how data moves between systems.
Data sources
| Source | What it provides |
|---|---|
| Jira REST API | CVE tracker ticket fields (status, timestamps, labels, custom fields) |
Jira whiteboard (customfield_10841) |
Per-ticket timestamp cache written back by the analysis tool |
Red Hat Pulp (packages.redhat.com) |
SRPM/RPM publish timestamps for Hummingbird repos |
| Hummingbird container catalog API | Image rebuild history (when a package first appeared in a rebuilt image) |
Red Hat CSAF VEX feed (security.access.redhat.com) |
Advisory fix/not-affected status per CVE |
OSIDB (osidb.prodsec.redhat.com) |
Subpackage-level affectedness data |
| NVD / CVE list | CVE publish dates, product/version data |
| GitHub / GitLab | Upstream fix commit / PR / release dates |
| Fedora updates | Fedora update availability timestamps |
| Konflux SNS/SQS events | Pipeline run, snapshot, release, MR, push events |
PostgreSQL databases
There are two Postgres databases.
1. hummingbird-status — Konflux pipeline events
Fed by SNS/SQS events via the hummingbird-status ingestor.
| Table | Primary key | What is stored |
|---|---|---|
gitlab_pushes |
(sha, repo, ref) |
Git push events — sha, branch, commit list |
components |
name |
Konflux component definitions and git context |
pipelineruns |
name |
Build/test PLR outcomes, status, start/completion times |
snapshots |
name |
Multi-component snapshots, source PLR, sha |
releases |
name |
Release outcomes, images, LLM analysis text |
gitlab_merge_requests |
(project, iid) |
Current MR state, merge commit sha |
gitlab_mr_versions |
(project, iid, sha) |
Per-commit history of each MR head |
2. hummingbird-dashboard — CVE lifecycle + dashboard overlays
| Table | Primary key / unique | What is stored |
|---|---|---|
cve_ticket_events |
(ticket_key, event_type) |
One row per lifecycle milestone per ticket. occurred_at = timestamp; metadata = JSONB (see below). The source of all R-Time computations. |
cve_analysis_log |
id |
Each analysis tool run: timestamp, ticket count, log output |
cve_ticket_claims |
ticket_key |
Claim/lock for deduplicating concurrent analysis runs |
dashboard_settings |
key |
Runtime flags: auto-rerun enabled, analysis enabled, etc. |
auto_rerun_log |
id |
History of automatic retrigger attempts |
blocked_error_patterns |
id |
Regex patterns that suppress auto-rerun |
blocked_snapshots |
snapshot_name |
Manually blocked snapshots |
analysis_log / analysis_costs |
id |
LLM failure analysis runs and token costs |
blocked_push_builds / push_build_rerun_log |
id |
Push build blocking and retry history |
package_lifecycle |
(package, event_type) |
Package-scoped lifecycle milestones (e.g. rpm_first_published). Distinct from cve_ticket_events — one row per package/milestone, not per ticket. |
cve_ticket_events lifecycle milestone event_type values
These are the canonical names after the HUM-5918 migration:
event_type |
Meaning |
|---|---|
cve_published |
CVE published date (NVD / CVE list) |
hum_ticket_created |
HUM Jira ticket creation date |
hum_ticket_closed |
HUM Jira ticket resolution date |
upstream_fix_merged |
Upstream fix commit / release merged |
fedora_update_available |
Fedora update containing the fix became available |
rpm_fix_published_to_pulp |
Fix RPM published to Hummingbird Pulp repo |
image_rebuilt_on_quay |
Hummingbird container image rebuilt with the fix |
vex_resolved |
Red Hat CSAF VEX advisory confirmed the resolution (HUM-5843) |
rpm_fix_published_to_pulp and image_rebuilt_on_quay are mutable — they
are updated when a newer delivery event supersedes the previous one. All other
event types are write-once: once set, occurred_at is never overwritten.
cve_ticket_events.metadata JSONB fields
Each row carries a metadata blob that reflects the ticket’s state at the time
of the most recent analysis run:
| Field | Source | Description |
|---|---|---|
computed_resolution |
analysis tool | Hummingbird’s computed fix status |
jira_status |
Jira status field |
Current Jira issue status |
labels |
Jira labels field |
All labels on the ticket |
fixed_in_build |
Jira customfield_10578 |
SRPM set manually in the “Fixed in Build” field |
detected_fixed_build |
Pulp / SRPM detection | SRPM filename auto-detected from Pulp repodata |
vex_status |
Red Hat VEX feed | fixed / known_not_affected / … |
vex_match_state |
reconciliation logic | matched / pending / mismatch |
vex_resolved |
VEX reconciliation | Timestamp when VEX first agreed with Jira resolution |
Jira whiteboard (customfield_10841)
The CVE analysis tool uses the Jira whiteboard field as a per-ticket timestamp cache. This is being phased out in favour of Postgres as the durable store (HUM-5917), but is still the source for a subset of fields.
The whiteboard holds compact JSON. The relevant sub-key is cve_cycle:
cve_cycle key |
Meaning | Mutable? |
|---|---|---|
cve_published |
CVE publish date | No — write-once |
jira_created |
HUM ticket creation date | No — write-once |
jira_closed |
HUM ticket close date | No — disabled (255-char limit) |
upstream_fix |
Upstream fix timestamp | No — write-once |
fedora_fix |
Fedora update timestamp | No — write-once |
hb_rpm_fix |
RPM published to Pulp | Yes — re-evaluated each run |
hb_image_fix |
Image rebuilt on Quay | Yes — re-evaluated each run |
The whiteboard is read and written only by the CVE analysis tool. The
dashboard never reads it directly; its authoritative source is always
cve_ticket_events.
Jira fields read by the CVE analysis tool
On each run the analysis tool fetches every open HUM CVE tracker ticket and reads the following fields from the Jira REST API:
| Jira field / custom field | Purpose |
|---|---|
summary |
Ticket title / package detection |
status, resolution, resolutiondate |
Ticket lifecycle state |
created |
Jira ticket creation date → hum_ticket_created |
description, comment |
CVE ID extraction, fix evidence |
labels |
cve-next-release, fix-in-progress, etc. |
security |
Embargo level |
assignee |
Ticket owner |
customfield_10578 (Fixed in Build) |
Manually set SRPM identifying the fix build |
customfield_10841 (Whiteboard) |
Cached cve_cycle timestamps (read + write) |
customfield_10667 (CVE ID) |
Structured CVE identifiers |
customfield_10860 (Embargo Status) |
Embargo flag |
customfield_10020 (Sprint) |
Sprint membership |
customfield_10014 (Epic Link) |
Parent epic |
Data flow
┌─────────────────────────────────────────────────────────────────┐
│ External data sources │
│ │
│ Jira REST API ─────────────────────────────────────┐ │
│ NVD / CVE list ────────────────────────────────────┤ │
│ GitHub / GitLab (upstream fix commits) ────────────┤ │
│ Fedora updates ────────────────────────────────────┤ │
│ Red Hat Pulp (RPM publish times) ─────────────────►│ │
│ Hummingbird catalog API (image rebuild times) ─────┤ │
│ Red Hat CSAF VEX feed ─────────────────────────────┤ │
│ OSIDB (subpackage affectedness) ───────────────────┘ │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ CVE analysis tool (cron, hummingbird-cve-analysis) │
│ │
│ • Reads Jira ticket fields + whiteboard cache │
│ • Resolves fix SRPM from Pulp repodata │
│ • Resolves image rebuild timestamp from catalog API │
│ • Checks upstream PR/release dates (GitHub/GitLab) │
│ • Fetches CVE publish date (NVD/CVE list) │
│ • Reconciles VEX status (CSAF feed) │
│ • Checks subpackage affectedness (OSIDB) │
│ │
│ Writes back to: │
│ ├── Jira whiteboard (cve_cycle timestamp cache) │
│ ├── Jira labels / Fixed-in-Build field │
│ ├── Jira comments │
│ └── dashboard DB → cve_ticket_events (one row per milestone) │
│ cve_analysis_log (run record) │
└──────────────────────────────┬───────────────────────────────────┘
│
┌───────────────────┴───────────────────┐
│ │
▼ ▼
┌──────────────────────────┐ ┌───────────────────────────────┐
│ Jira whiteboard │ │ dashboard DB │
│ (per-ticket JSON cache) │ │ cve_ticket_events table │
│ cve_cycle timestamps │ │ one row per (ticket, │
│ ← being phased out │ │ event_type) milestone │
│ (HUM-5917) │ └───────────────┬───────────────┘
└──────────────────────────┘ │
▼
┌──────────────────────────────────┐
│ hummingbird-dashboard API │
│ │
│ Pivots cve_ticket_events rows │
│ into per-ticket dicts, computes:│
│ • entry-level R-Time fields │
│ (HUM-5920) │
│ • duration legs inside stages │
│ (HUM-5921) │
│ │
│ Serves JSON + Jinja templates │
└──────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ Konflux SNS/SQS event stream │
│ │
│ GitLab pushes, PipelineRuns, Snapshots, Releases, MRs │
│ → hummingbird-status ingestor │
│ → hummingbird-status DB (pipeline/release tables) │
│ → hummingbird-dashboard API (build/release views) │
└─────────────────────────────────────────────────────────┘
API field names
The dashboard API exposes these computed fields per R-Time entry:
Entry-level fields
| API field | Meaning |
|---|---|
cve_published_at |
Start of R-Time (CVE publish date, or upstream fix if later) |
fix_delivered_at |
Image delivery date (RPM fallback) |
cve_to_delivery_hours |
Total R-Time: cve_published_at → fix_delivered_at |
cve_to_hum_created_hours |
Filing lag: CVE publish → HUM ticket opened |
fix_before_cve_published |
True when RPM/image shipped before CVE was published |
hum_ticket_open |
True for unresolved pre-built cases (R-Time still accumulating) |
deferred_to_next_release |
True for cve-next-release tickets |
display_duration_hours |
Display-safe duration (elapsed so far for open tickets) |
Duration legs (stages dict)
| API field | Interval |
|---|---|
cve_published_to_hum_created |
CVE publish → HUM ticket opened |
cve_published_to_upstream_fix |
CVE publish → upstream fix merged |
hum_created_to_upstream_fix |
HUM ticket → upstream fix merged |
upstream_fix_to_fedora_update |
Upstream fix → Fedora update available |
fedora_update_to_rpm_fix_published |
Fedora update → fix RPM in Pulp |
upstream_fix_to_rpm_fix_published |
Upstream fix → fix RPM in Pulp |
hum_created_to_rpm_fix_published |
HUM ticket → fix RPM in Pulp |
rpm_fix_published_to_image_rebuilt |
Fix RPM in Pulp → image rebuilt on Quay |
image_rebuilt_to_hum_closed |
Image rebuild → HUM ticket closed |
Aggregate stats
| API field | Meaning |
|---|---|
avg_hum_created_to_rpm_fix_hours |
Mean HUM ticket → RPM fix (excludes pre-built) |
avg_rpm_fix_to_image_rebuilt_hours |
Mean RPM publish → image rebuild |
Package lifecycle data
rpm_first_published is the earliest timestamp at which any SRPM for a given
package appeared in the Hummingbird Pulp repo. It is package-scoped — one
row per package — as opposed to cve_ticket_events which is ticket-scoped.
Collection
scripts/collect_rpm_first_published --prod --rpms-repo /path/to/rpms
Flow:
- Loads the package list from
rpms_repo.load_package_map_from_metadata(). - For each package: calls
pulp.fetch_earliest_srpm_time(), which browsespackages.redhat.com/.../source/Packages/{letter}/, parses the HTML listing already used by the analysis tool, and returns the earliest upload timestamp across all SRPMs for that package. - POSTs all results in one request to
/api/cve-import(same endpoint used forcve_ticket_eventssync). The dashboard upserts withCOALESCE(LEAST(existing, incoming), existing, incoming)— re-runs only updateoccurred_atif the incoming timestamp is earlier, and NULLs are never stored over a real value.
Surfaced in dump_lifecycle
scripts/dump_lifecycle --prod HUM-1234
After fetching ticket milestones from cve_ticket_events, the script resolves
the package name from those rows and makes a second call to
/api/cve-export?section=package_lifecycle to fetch rpm_first_published for
that package. It is shown at the bottom of the text output and under
rpm_first_published in the JSON output.