{% if render_mode != 'fragment' %} {% if domain %}{% endif %} Human Readable SBOM - Finite State Report {# No charts by design (output.charts: []) — the table IS the deliverable. ECharts is deliberately NOT included: a chart on a 795-row inventory pushes the actual content below the fold. #} {% include "_design_system.html" %} {% include "_console_shell.html" %} {% endif %} {# Recipe-local styles — emitted in BOTH modes so fragment_extractor collects and scopes them under .fs-section-human-readable-sbom. #} {% if render_mode != 'fragment' %} {% endif %} {% import "_console_macros.html" as fs with context %} {# Defensive defaults — keep the template renderable if the transform short-circuited. Mirrors cve_component_evidence.html. #} {% set transform_result = transform_result | default({}) %} {% if not transform_result is mapping %}{% set transform_result = {} %}{% endif %} {% set sbom = transform_result.get('sbom_summary', {}) %} {% set notes = transform_result.get('notes', []) %} {% set data = data | default([]) %} {% set show_policy = sbom.get('include_policy_status', True) %} {% set show_findings = sbom.get('include_finding_counts', True) %} {% set sev = sbom.get('severity_totals', {}) %} {% if render_mode != 'fragment' %} {{ fs.topbar( crumbs=["Finite State", "Human Readable SBOM"], meta=[ {"label": "Domain", "value": domain or "—"}, {"label": "Project", "value": sbom.get('project_name') or project_label or "—"}, {"label": "Version", "value": sbom.get('version_name') or "—"}, {"label": "Generated", "value": generated_at or "—"}, ], controls=[], ) }} {% endif %}

Human Readable SBOM

Every component in this project version, with its licensing and origin{% if show_findings %} and finding counts{% endif %}. Nothing is truncated.

{% if sbom %}
{{ fs.kpi_cell("Components", "{:,}".format(sbom.get('total_components', 0))) }} {% if show_findings %} {{ fs.kpi_cell("With Findings", "{:,}".format(sbom.get('components_with_findings', 0))) }} {{ fs.kpi_cell("Total Findings", "{:,}".format(sbom.get('total_findings', 0))) }} {{ fs.kpi_cell( "Critical", "{:,}".format(sev.get('CRITICAL', 0)), dot=("critical" if sev.get('CRITICAL', 0) > 0 else None), ) }} {{ fs.kpi_cell( "High", "{:,}".format(sev.get('HIGH', 0)), dot=("high" if sev.get('HIGH', 0) > 0 else None), ) }} {# All four tiers, not just the top two: the table breaks findings out into four severity columns and the Markdown summary and JSON severity_totals both carry four. Stopping at High made HTML the one format whose summary disagreed with its own table. The bar is an auto-fit grid, so the extra cells wrap rather than crowd. #} {{ fs.kpi_cell( "Medium", "{:,}".format(sev.get('MEDIUM', 0)), dot=("medium" if sev.get('MEDIUM', 0) > 0 else None), ) }} {{ fs.kpi_cell( "Low", "{:,}".format(sev.get('LOW', 0)), dot=("low" if sev.get('LOW', 0) > 0 else None), ) }} {% endif %} {% if show_policy %} {{ fs.kpi_cell( "Policy Violations", "{:,}".format(sbom.get('total_violations', 0)), dot=("critical" if sbom.get('total_violations', 0) > 0 else None), ) }} {# Warnings alongside violations: the table's Policy cell carries both, the Markdown summary prints both and JSON has total_warnings. A headline showing only violations reads amber as zero. #} {{ fs.kpi_cell( "Policy Warnings", "{:,}".format(sbom.get('total_warnings', 0)), dot=("medium" if sbom.get('total_warnings', 0) > 0 else None), ) }} {% endif %}
{% endif %} {% if notes %}
    {% for note in notes %}
  • {{ note }}
  • {% endfor %}
{% endif %}
{{ fs.panel_head( "Components", meta=("{:,}".format(data | length)) ~ " component" ~ ("s" if (data | length) != 1 else "") ) }}
{% if data and data | length > 0 %} {% if show_policy %}{% endif %} {% if show_findings %} {% endif %} {% for row in data %} {% if show_policy %} {% endif %} {% if show_findings %} {% for key, cls in [('critical', 'sbom-sev-critical'), ('high', 'sbom-sev-high'), ('medium', 'sbom-sev-medium'), ('low', 'sbom-sev-low')] %} {% set n = row.get(key, 0) or 0 %} {% endfor %} {% endif %} {% endfor %}
Name VersionPolicyFindings C H M LType Supplier Licenses Release Date Source Status Component ID
{{ row.get('component_name') or '—' }} {{ row.get('version') or '—' }} {% set v = row.get('violations', 0) or 0 %} {% set w = row.get('warnings', 0) or 0 %} {# Zero renders as 0, not an em dash: these are count columns, and CSV/JSON carry 0 here. An em dash would make "no violations" indistinguishable from "not measured" in the primary human-readable artifact. #} {{ "{:,}".format(v) }}    {{ "{:,}".format(w) }} {{ "{:,}".format(row.get('findings', 0) or 0) }}{{ "{:,}".format(n) }}{{ row.get('component_type') or '—' }} {{ row.get('supplier') or '—' }} {{ row.get('licenses') or '—' }} {{ row.get('release_date') or '—' }} {{ row.get('source') or '—' }} {{ row.get('status') or '—' }} {{ row.get('component_id') or '—' }}
{% else %}

No components were returned for this project version. {% if not sbom.get('include_file_components', False) %} File-type components are excluded by default — pass --include-file-components if this version contains only file entries. {% endif %}

{% endif %}
{% include "_columns_schema.html" ignore missing %}
{% if render_mode != 'fragment' %} {# status_bar takes plain strings, not (label, value) pairs — a tuple renders as its Python repr. #} {{ fs.status_bar(items=[ "Components: " ~ "{:,}".format(sbom.get('total_components', 0)), "File components: " ~ ("included" if sbom.get('include_file_components', False) else "excluded"), "Domain: " ~ (domain or "—"), ]) }} {% endif %} {% if render_mode != 'fragment' %} {% endif %}