"""Read a CycloneDX SBOM's flat component list into something addressable by bom-ref.

CycloneDX keeps two views of the same tree: `components` is a flat list — every component the
scanner found, at any depth — and `dependencies` (see `graph.py`) is the edge list between their
`bom-ref`s. This module only reads the flat list. The root application itself
(`metadata.component`) is a component too and belongs in the same dict, or `graph.py` cannot
look it up by its ref when it walks the edges.
"""
from dataclasses import dataclass


@dataclass(frozen=True)
class Component:
    ref: str
    name: str
    version: str


def load_components(sbom: dict) -> dict[str, Component]:
    """Return every component in `sbom`, keyed by its `bom-ref` — the root application at
    `sbom["metadata"]["component"]` plus every entry in `sbom["components"]`.

    A component with no `"version"` key (CycloneDX allows omitting it) becomes `version=""`,
    never a `KeyError`.
    """
    ...
