Roadmap
2026-10-14 · Project Board → · Milestones: v0.8.0 · v0.9.0 · v1.0.0 · v1.1.0 · v1.2.0
This page summarises ROADMAP.md, which is authoritative and carries the full reasoning. Both are updated when a release is cut, not in feature pull requests.
Vision
BOMHort is transitioning from a single-instance SBOM visualization tool into an enterprise-grade, multi-cluster Software Supply Chain Security platform. Phase 1 (foundation, auth, multi-cluster model, push ingestion) shipped in v0.4–v0.7.
The roadmap is organised around one hard deadline — the v1.0.0 schema and API freeze — and one regulatory fact: the EU Cyber Resilience Act’s vulnerability-reporting obligations are in force since 2026-09-11, and customers already ask for a CRA-grade vulnerability register. The CRA scope therefore moved into 1.0 (re-plan 2026-09-25), and 1.0 is reached in three steps:
| Release | Due | Theme |
|---|---|---|
| v0.8.0 ✅ | 2026-10-31 | Contract — MCP server, project aggregation, source_repo fix, values.yaml shape, CVE ids, CSV export, license provenance |
| v0.9.0 | 2026-11-30 | Vulnerability register — CVSS, CWE, KEV, EPSS, remediation record, SLA due dates (#414) |
| v1.0.0 | 2027-01-31 | Freeze + CRA dashboard — readiness score, MTTR, auditor report bundle, crypto-library inventory, versioned docs |
| v1.1.0 | 2027-04-30 | Automation, fleet & cryptography — VEXViper, fleet views, OSV mirror, attestations, CBOM |
| v1.2.0 | 2027-07-31 | Analytics — Scorecard, Lottery Factor, SBOM diff, tree view, blast radius, enriched export |
Two rules drive sequencing:
- If it can’t be back-filled, it lands before 1.0; if it’s additive, it lands after. The register work is additive and lands before 1.0 for market reasons, not contract reasons — the Schema Change Register says which is which.
- Issues raised by the consumer side ship first. #398 and #399 came from someone building on BOMHort; they opened v0.8.0.
Phase 1: Foundation & Security ✅
Q1–Q2 2026 · Complete. Production-ready with real security requirements.
| Status | Issue | Description |
|---|---|---|
| ✅ | cluster column on all core tables (migration 012). | |
| ✅ | Service token + API key modes. Gate for all write operations. | |
| ✅ | /readyz, /livez for K8s probes. | |
| ✅ | API-only deployment without Angular UI. | |
| ✅ | Helm Ingress template + TLS. | |
| ✅ | Group SBOMs by project. | |
| ✅ | Download SBOM JSON from the platform. | |
| ✅ | Parse CycloneDX 1.4+ SBOMs. | |
| ✅ | Cross-org dependency consistency. | |
| ✅ | GET /api/v1/clusters, per-cluster stats and SBOM lists. | |
| ✅ | POST /api/v1/sboms/upload from CI/CD pipelines. | |
| ✅ | GET /api/v1/projects/{name} + sub-resources, de-duplicated counts; the project identity rule is contract. Shipped in v0.8.0. | |
| 🟡 | #136 Enhanced CORS | Functionally done (POST on upload, X-API-Key). Remaining bits (CORS_ALLOW_CREDENTIALS, configurable methods) are additive → v1.1.0. |
Schema wave 014–022 — complete: document_store (#256), namespace/project (#138, #57), source_repo/source_ref (#332), VEX provenance (#334), VEX SBOM scope (#350), OSV aliases, VEX product_ref, document_version, tags (#357). 023–026 followed in v0.8.0; the v0.9.0 register work starts at 027.
Delivered beyond the roadmap: Global Search, Package Search, in-toto attestation unwrapping, protobom parsing backend, license resolution via GitHub + npm + NuGet with license-text classification, SPDX license expression evaluation (#402), dark mode, white-label theming, Prow chat-ops (#405).
Phase 2: The road to 1.0
Oct 2026 – Jan 2027 · Theme: Freeze a contract that an external consumer has already exercised (#399), and ship a CRA-grade vulnerability register inside the frozen surface rather than bolting it on after.
v0.8.0 — Contract ✅
| Status | Issue | Description |
|---|---|---|
| ✅ | Five read-only tools over the REST API (cmd/mcp-server), no ClickHouse credentials. stdio by default; Streamable HTTP refuses to start without a bearer token and a non-wildcard Origin allow-list. See MCP Server. | |
| ✅ | The SBOM Explorer reads by project, not by document — same de-duplication as #398. | |
| ✅ | source_repo on real SBOMs | documentNamespace fallback, release/tag/commit URL handling, CycloneDX distribution. Existing rows need a re-parse. |
| ✅ | existingConfigMap | License policy and exceptions mount from an externally managed ConfigMap. |
| ✅ | A leftover seedJob block fails helm template with a message naming the alternatives. | |
| ✅ | 24.8 LTS, pinned by digest; CI runs every query against 24.8 and 24.12. | |
| ✅ | Project stats read only the selected projects’ SBOMs; apiGateway.queryLimits.* bounds gateway queries (on by default). A–D, F–H stay post-1.0. | |
| ✅ | cve_id and aliases on findings, VEX statements and search; lookups by any alias. | |
| ✅ | GET /api/v1/reports/vulnerabilities?format=csv, streamed, formula-injection safe. | |
| ✅ | deps.dev/Packagist/PyPI resolvers, unapproved category, per-package license source (migration 024). See License Resolution. |
v0.9.0 — Vulnerability register
Due 2026-11-30. The #414 umbrella: CRA Annex I Part II made queryable — per finding and per deployed version: CVE, CWE, CVSS, EPSS, KEV status, remediation status, due date, and a timestamp proving it is current.
| Status | Issue | Migration | Description |
|---|---|---|---|
| 🔲 | #408 CVSS score, vector, version (incl. v4) | 027 | Score is computed in osvutil today and discarded. Backfill from osv_json. |
| 🔲 | #409 CWE ids | 027 | From OSV database_specific.cwe_ids. Enables crypto CWE filters. |
| 🔲 | #410 CISA KEV status | 028_create_kev_catalog | Daily feed; the public signal for “actively exploited” (CRA Art. 14, 24 h). Brings a due date. |
| 🔲 | #64 EPSS scores | 029_create_epss_scores | Pulled forward from v1.2.0; shares the refresher plumbing with KEV. |
| 🔲 | #413 VEX action statement as remediation record | 030 | action_statement_timestamp on vex_statements. |
| 🔲 | #411 Remediation SLA policy | none | remediation-policy.json → derived due_date, overdue, remediation_status. No write API. |
| 🔲 | #414 Register umbrella | — | Docs page, last_refreshed_at on export and dashboard, final CSV column list. |
v1.0.0 — Freeze + CRA dashboard
Due 2027-01-31, after a four-week soak of v0.9.0 on the CNCF instance.
| Status | Issue | Description |
|---|---|---|
| 🔲 | #141 CRA compliance dashboard | Readiness score per project/cluster, computed from what v0.9.0 stores. #140/#143 become additional inputs in v1.1.0, not prerequisites. |
| 🔲 | #7 CVE fix time (MTTR) | 031_create_vulnerability_resolutions. Stretch — drops to v1.1.0 if the soak needs the time. |
| 🔲 | #62 Auditor report bundle | CSV + JSON bundle with a manifest. PDF only after the library decision; not a blocker. |
| 🔲 | #419 Crypto-library inventory | From existing SBOMs by PURL match (032); no CBOM needed. |
| 🔲 | #145 Versioned documentation | Ships with the tag. |
| 🔲 | Migration guide + values.yaml review | Every key added since v0.7: mcp.*, existingConfigMap, seedJob removal, apiGateway.queryLimits.*, image pin, kev.*, epss.*, remediationPolicy.*, cryptoLibraries.*. |
What v1.0 means
- API contract frozen — no endpoint removals or response shape changes without v2.0
- ClickHouse schema stable — no
ORDER BYor column-type changes;ADD COLUMN … DEFAULTand new tables remain allowed - Helm values stable — existing
values.yamlkeys won’t be renamed - Supported ClickHouse floor — 24.8 LTS, covered by CI (#392) ✅
- Support policy active — current release + 2 previous minors receive security patches (see Support Policy)
- A CRA-grade vulnerability register is exportable per deployed version, and a readiness score is computed from it
All v0.x releases are development milestones and may contain breaking changes between minor versions — read the release notes before upgrading.
Phase 3: Automation, Fleet & Cryptography
v1.1.0 · due 2027-04-30.
Epic #338 — Automated VEX generation (VEXViper)
VEXViper is an out-of-tree Go sidecar: it reads findings via the REST API, gathers evidence, asks a configurable LLM or rule engine, and uploads validated OpenVEX back. The correctness blockers (#332, #335, #355) have all landed.
| Status | Issue | Description |
|---|---|---|
| 🔲 | #336 Idempotent VEX upload + job status | Content-hash dedupe; GET /api/v1/uploads/{job_id}. New table 03x_create_upload_jobs. |
| 🔲 | #333 Incremental listing + vex_status=missing | ?since=&cursor= on /sboms. Query-only. |
| 🔲 | #334 Provenance UI | Automated vs. human badge, status_notes, ?vex_source=. |
| 🔲 | #337 Outbound webhooks | HMAC-signed sbom.ingested, findings.updated, vex.applied, upload.rejected. |
Fleet operations
| Status | Issue | Description |
|---|---|---|
| 🔲 | #138 Namespace filtering (API + UI) | ?namespace= on list endpoints, namespace chips. |
| 🔲 | #267 → #176 Cluster Picker | Query-param filter first (help wanted), then navbar dropdown. |
| 🔲 | #140 Workload vulnerability summary | Image → posture; additional #141 input. |
| 🔲 | #57 Per-project policies | License policies, severity thresholds, exception scopes per project. |
| 🔲 | #136 CORS (remaining) | CORS_ALLOW_CREDENTIALS, configurable methods/headers. |
| 🔲 | #60 Local OSV mirror | Offline / air-gapped; KEV and EPSS feeds get the same treatment. |
| 🔲 | #143 In-toto Witness integration | 03x_create_attestations, signature verification; additional #141 input. |
Cryptography — #420 (CBOM)
| Status | Issue | Description |
|---|---|---|
| 🔲 | #415 CycloneDX 1.6 crypto assets | 03x_create_crypto_assets. |
| 🔲 | #416 Cryptographic inventory | Algorithms, protocols, certificates, keys per project/fleet. |
| 🔲 | #417 Crypto policy + exceptions | crypto-policy.json, BSI TR-02102 / NIST SP 800-131A example profiles. |
| 🔲 | #418 PQC readiness | quantum_vulnerable / hybrid / pqc classification, readiness % per project. |
Phase 4: Analytics
v1.2.0 · due 2027-07-31. CRA scoring left this phase for 1.0; what remains is prioritisation and dependency-health depth.
| Status | Issue | Description |
|---|---|---|
| 🔲 | #255 Enriched SBOMs + enriched download | Overlay on the #256 originals; companion VEX; in-toto re-sign. |
| 🔲 | #254 protobom/storage schema evaluation | Research; informs #255. Not a rewrite of sbom_packages. |
| 🔲 | #38 SBOM Diff | Dependency tree divergence between versions. |
| 🔲 | #56 Dependency Tree View | Hierarchical visualization of transitive chains. |
| 🔲 | #63 Blast Radius Search | Version-constrained impact analysis. |
| 🔲 | #61 OpenSSF Scorecard | Upstream project health per dependency. |
| 🔲 | #82 Lottery Factor | Single-maintainer risk detection. |
| 🔲 | #268 Official ClickHouse operator | Breaking values.yaml change → v2.0 candidate. |
Schema Change Register
Everything that touches db/migrations/ or a frozen response shape. The authoritative register — including the “needs pre-1.0?” reasoning per row — is the one in ROADMAP.md; check it, upstream main and open pull requests before claiming a number. After 1.0, ORDER BY and column-type changes are never allowed; ADD COLUMN … DEFAULT and new tables are fine at any time.
| Migration | Issue | Change | Pre/Post 1.0 |
|---|---|---|---|
012_add_cluster_column | #131 | ADD COLUMN cluster | ✅ shipped |
013_create_registry_license_cache | #330 | New table | ✅ shipped |
014_create_document_store | #256 | New table | ✅ shipped (pre) |
015_add_namespace_project_columns | #138, #57 | ADD COLUMN namespace, project (core tables + document_store) | ✅ shipped (pre) |
016_add_source_columns | #332 | ADD COLUMN source_repo, source_ref (sboms + ingestion_queue) | ✅ shipped (pre) |
017_add_vex_provenance | #334 | ADD COLUMN author, role, tooling, status_notes | ✅ shipped (pre) |
018_add_vex_sbom_scope | #350 | ADD COLUMN sbom_id on vex_statements + target_sbom_id on ingestion_queue — VEX scoped to its SBOM | ✅ shipped (pre) |
019_add_vulnerability_aliases | — | ADD COLUMN aliases on vulnerabilities (GHSA ↔ CVE); VEX matches by alias | ✅ shipped (pre) |
020_add_vex_product_ref | — | ADD COLUMN product_ref on vex_statements (VEX rescue pass) | ✅ shipped (pre) |
021_add_document_version | — | ADD COLUMN document_version on sboms | ✅ shipped (pre) |
022_add_sbom_tags | #357 | ADD COLUMN tags on sboms + ingestion_queue | ✅ shipped (pre) |
023_add_project_parent | — | ADD COLUMN parent on sboms/ingestion_queue, root_purl, supplier on sboms (project groups) | ✅ shipped (pre) |
024_add_package_license_sources | #439 | ADD COLUMN package_license_sources on sbom_packages — where each license came from or why it is missing (License Resolution) | ✅ shipped (pre) |
025_add_dependency_depth | — | ADD COLUMN package_depths on sbom_packages, dependency_depth on vulnerabilities (direct vs. transitive) | ✅ shipped (pre) |
026_add_queue_retry_after | — | ADD COLUMN retry_after on ingestion_queue (defer jobs on a GitHub rate limit) | ✅ shipped (pre) |
| — | #335 | Row semantics of /sboms/{id}/vulnerabilities | ✅ shipped (pre, API) |
| — | #177 | cluster in SBOMListItem | ✅ shipped (pre, API) |
| — | #398 | De-duplicated project counts; project identity rule is contract | ✅ shipped (pre, API) |
| — | #399, #397, #391, #392, #344-I | mcp.*, existingConfigMap, seedJob removed, ClickHouse image pin, apiGateway.queryLimits.* | ✅ shipped (pre, Helm values) |
| — | #412, #266 | cve_id + aliases on findings; CSV export endpoint | ✅ shipped (pre, API) |
| — | #411 | remediation-policy.json; derived due_date/overdue, no storage | pre (v0.9.0, values) |
| — | #141, #62 | CRA readiness score; report bundle | pre (v1.0.0, API) |
027_add_vulnerability_cvss_cwe | #408, #409 | CVSS score/vector/version and CWE IDs on vulnerabilities | pre (v0.9.0) |
028_create_kev_catalog | #410 | New table | pre (v0.9.0) |
029_create_epss_scores | #64 | New table | pre (v0.9.0) |
030_add_vex_action_statement_timestamp | #413 | ADD COLUMN action_statement_timestamp on vex_statements | pre (v0.9.0) |
031_create_vulnerability_resolutions | #7 | New table | pre (v1.0.0, stretch) |
032_create_crypto_libraries | #419 | New table (or MV over sbom_packages) | pre (v1.0.0) |
03x_create_package_index_mv | #344-C/D/E | MV + skip indexes | post |
03x_create_upload_jobs | #336 | New table | post |
03x_create_attestations | #143 | New table | post |
03x_create_crypto_assets, 03x_create_crypto_compliance | #415, #417 | New tables | post (v1.1.0) |
03x_* | #61, #82, #255, #60 | New tables | post |
| — | #268 | Operator swap | v2.0 |
Dependency Graph
PRE-1.0 contract:
#398 ✅ ──┬── #58 ✅ (Aggregated SBOM View) v0.8.0
└── #399 ✅ (MCP: get_project) ── post-1.0: write tools
REGISTER (#414):
#412 ✅ (cve_id/aliases) ── #410 (KEV, matched by alias) ──┐
#408 (CVSS) ─────────────────────────────────────────────┼── #411 (SLA due date; KEV due date overrides) ──┐
#409 (CWE) ──────────────────────────────────────────────┤ ├── #141 (CRA score) v1.0.0
#64 (EPSS) ─────────────────────────────────────────────┤ ├── #62 (report bundle)
#413 (VEX action statement) ─────────────────────────────┘ └── #7 (MTTR)
#266 ✅ (CSV) ── grows with every row above ── #62
CRYPTO (#420):
#419 (library inventory, SBOM-only) v1.0.0
#415 (CBOM ingest) ── #416 (inventory) ── #417 (policy) ── #418 (PQC) v1.1.0
└── #409 (CWE-327 filter on the register)
VEXVIPER (#338):
#355 ── #336 (idempotent upload) ── #333 (since/cursor) ── #337 (webhooks) ── #334 UI
FLEET:
#131 ── #132/#133 ── #177 ── #267 ── #176
└── #138 ── #140 ──┐
#143 (Witness) ─────────┴── additional #141 inputs (v1.1.0)
#60 (OSV/KEV/EPSS mirror) ── standalone
#61, #82 ── extend internal/github #254 ── informs #255 #268 ── v2.0
Prioritization
Why the CRA moved into 1.0
The reporting obligation is in force, and its 24-hour clock for actively exploited vulnerabilities is exactly what KEV status (#410) makes visible. Customers ask for a register now, column by column. Every register item is additive, so this does not break the back-fill rule — it is pre-1.0 because 1.0 is the release adopters evaluate against the CRA.
Why three releases instead of one
One milestone with 21 issues and a tag at the end slips. v0.8.0 kept its October date, v0.9.0 is the self-contained register, and v1.0.0 adds the score on top with a December soak.
Why VEXViper after the register
The register is what VEX statements are written against: #413 fixes what a statement records, #411 defines what “open” means, #410/#64 define what to triage first.
Cluster vs. namespace vs. project
| Dimension | Question | Example | Cardinality |
|---|---|---|---|
cluster | Where is it deployed? | prod-eu | 1–50 |
namespace | Which team boundary inside the cluster? | payments | 10–500 |
project | What is it / who owns it? | payment-service | 50–5000 |
All three are LowCardinality(String) DEFAULT '' columns, none in ORDER BY. tags label projects across these dimensions; they do not replace them.
Non-Goals
- ❌ Custom Kubernetes Operator (Helm + ClickHouse Operator)
- ❌ In-tree VEX generation / LLM calls (stays in the VEXViper sidecar; the MCP server is a transport)
- ❌ MCP write tools in 1.0 (read-only by design)
- ❌ Write APIs for policies or exceptions — license, remediation, crypto (frontend is public)
- ❌ Per-finding manual status or due dates (status from VEX, due dates from policy)
- ❌ CBOM generation or crypto scanning (BOMHort consumes CBOMs)
- ❌ CRA reporting to ENISA/CSIRTs (BOMHort tells you what and when; filing is your process)
- ❌ Multi-repo split (monorepo is a hard constraint)
- ❌ Real-time streaming (batch + webhooks is sufficient)
- ❌ RBAC/multi-tenancy (auth is binary for now)
- ❌ Full OIDC in BOMHort (upstream proxy responsibility)
- ❌ Relational rewrite of
sbom_packages(#254 informs the overlay only)
Contributing
Want to pick up an issue from the roadmap? Check the Project Board for items in the Todo column. Issues labeled help wanted or good first issue — for example #267 — are especially good for new contributors.
See Development Guide for setup instructions.