Handing a release to a requirements-management tool (ReqIF)
Teams that link threat models, risk registers, test records and software bills of materials in a requirements-management or application lifecycle management (ALM) tool exchange those links as ReqIF, the Object Management Group's Requirements Interchange Format. sbomflow export-reqif writes one release's engineering evidence in that form, so the tool you already use can import it beside the rest of your record.
It is a one-way handoff. SBOMFlow writes a file; it never reads a ReqIF document back, never uploads, and never talks to any tool.
Export one release as ReqIF#
Run it on an output directory sbomflow analyze or sbomflow audit wrote:
sbomflow export-reqif evidence/ --output handoff/release.reqif --as-of 2026-09-01T00:00:00ZIt writes handoff/release.reqif and handoff/reqif-export-receipt.json beside it. The output directory is read, never written: --output must be outside it. Before anything is written, the release record must match the run-completion seal the run wrote, the evidence pack must hash to the digest that record states, and both files pass the same share-boundary preflight every export passes.
What the document holds#
Four kinds of object (ReqIF SpecObjects), each with a type of its own:
| Type | One object per | sbomflow.state is | sbomflow.review_status is |
|---|---|---|---|
SBOMFlowRequirement | requirement node the run's requirement regime assessed, and requirement of a user-supplied catalog the run evaluated | the node's status (for example not_automatically_assessable), or the catalog requirement's state | the node's review state, or unreviewed |
SBOMFlowGap | evidence gap | evidence_gap | unreviewed |
SBOMFlowFinding | vulnerability finding, by its recorded finding_key | its vex_status | the status a reviewer's applied decision recorded, or unreviewed |
SBOMFlowEvidence | evidence item, and artifact the release record lists | the item's observed_status, or recorded | the item's review status |
A finding is linked to the component it names (affects_component), and a requirement node to the evidence items that support it (evidenced_by). A run executed with no requirement regime (requirement_regime: none) has no regime requirement nodes and no gaps, so it exports findings and evidence only.
Every value is a fact the release already recorded:
sbomflow.stateis the engine's own word, verbatim, andsbomflow.review_statusis what a person recorded — the two are never merged.sbomflow.official_referenceis a reference id and its URL (for example a regulation's annex point and its official address). It is never the text of any standard or regulation, and it is bounded in length; a user-supplied catalog's citation longer than that bound is left out and counted in the receipt, never cut short.sbomflow.evidencenames an artifact and its SHA-256.- The header's comment says what the document is: engineering evidence, not a statement of conformity with anything.
Identifiers that survive the next release#
Each object's IDENTIFIER is derived from a fact that does not change from one release of a product to the next: a requirement id, a gap id, a finding's finding_key, an evidence item's key and reference, an artifact's path, a component's Package URL without its version. Export the next release into the tool and it updates the objects it already holds instead of creating new ones. Two facts that would share an identifier refuse the export; they are never merged.
Change dates that change only with the object#
Each object's LAST-CHANGE is the date its content last changed — ReqIF defines it as "the date and time of the last change of the information element". Export the next release to the same --output as the previous one: every element whose content (its attributes, values and children) is unchanged since that export keeps the previous LAST-CHANGE, and only what changed, or is new, carries this export's time. The previous export is used only when its document still hashes to the digest its receipt records — a document edited after export carries nothing forward — and a date later than this export's creation time is never carried. The receipt records, per element, the digest of its content and the date written, and how many dates were carried (last_change). An unchanged date says the exported element did not change; it does not say anything was re-reviewed.
Deterministic, and checked#
The same output directory, --as-of and previous export write the same bytes. Without --as-of, the creation time is the evidence pack's own generated_at, never the clock.
The document is checked structurally before it is written: well-formed XML in the ReqIF namespace, the header elements the format requires, which elements each element may hold, one unique identifier per object with a change date, and every reference resolving to an object of the right kind. This is a structural check written against the format's element structure, not a validation against the format's published XML schema, and the receipt says so: it checks which elements each element may hold, not the order the schema's sequences put them in. The receipt also records the ReqIF 1.2 document by its address and by the SHA-256 of the formal PDF and of the XSD, measured on 2026-09-28; the XSD is not vendored (its licence has not been read), so the check stays structural.
The receipt#
reqif-export-receipt.json records the document's SHA-256, the release, product and requirement regime it came from, how the release record was verified, the object counts by source, and what is never exported. It also carries exploitation_delta. sbomflow store exploitation-delta answers which newly KEV-listed identifiers a stored release records and writes that answer to a file of its own. Name that file with --exploitation-delta FILE and each finding the delta names for this release carries sbomflow.exploitation_delta (for example newly_listed_kev: <ids> (KEV snapshots <from>..<to>)), and the receipt reads available; a release the delta did not examine reads not_available with the reason, never an empty value. The file is read offline and bounded, and a file whose schema_version is not sbomflow-exploitation-delta-v1 is refused (E016) with nothing written. Without the option no delta is read — none is guessed — and the receipt reads not_available with that reason. The delta file is the one store exploitation-delta ... --output kev-delta.json wrote; pass it as export-reqif EVIDENCE_DIR --output release.reqif --exploitation-delta kev-delta.json.