{% extends "base.html" %} {# Supply chain audit indicators. Flags render green (pass), red (fail) or neutral grey (not audited yet). Registration has a fourth state, 2, which renders yellow: the chain does carry a registration, but its *source* reference - the git commit, not the rpm-md binary checksum the build is keyed on - is too weak to verify against. The binary checksum cannot be the weak one: it is the lookup key, so a build either has a full digest or was never polled at all. Colour is never the only signal - every indicator carries a title with the spelled out state, and the security badge also names the worst severity and the issue count. The *_icon macros are the compact form for the build table, the *_detail macros the spelled out form used by supply_chain_audit_box(), the box shown inside Product Information. Icon names must exist in FontAwesome 6.0.0 (the version base.html loads) - later v6 names such as fa-shield-halved are not in it and render as nothing. #} {# Severity vocabulary of the security_issues column, worst first. Two of them, because the column has two producers. The chain monitor writes what the contract's SecurityLevel flag says (low, moderate, important, critical), and the import API lets a caller push the older low/medium/high/ critical wording. Both are listed so neither is dropped on the floor: a severity this list does not name used to render as green "none known", which states the opposite of the truth. Anything still unrecognized is shown too, in a neutral badge, and ranked ahead of everything we can rank: an unplaceable severity might be the worst one there is, and the badge is a warning rather than a score, so the safe reading is the loud one. See SEVERITY_ORDER in the JS below, which has to stay in step with this list. #} {% set severity_levels = ['critical', 'important', 'high', 'moderate', 'medium', 'low'] %} {% macro audit_flag(state, icon, label, ok_text, fail_text, pending_text='not audited yet', warning_text='weak source reference') -%} {%- if state is none -%} {%- elif state == 2 -%} {%- elif state -%} {%- else -%} {%- endif -%} {%- endmacro %} {# The severity is the whole answer, so nothing here counts anything. A build has exactly one security level: the contract derives it from the nearest report at or after that build, get_product_build() returns the one number, and security_issues_for() mirrors it as {level: 1}. The column is a dict only because it predates the chain being its only writer; the values are carried but never shown, because "1 low (1 total)" was arithmetic about a number that cannot vary. A level is present when its value is truthy, which is what keeps a stored zero from reading as a report. #} {% macro security_issues_icon(issues) -%} {%- if issues is none -%} {%- else -%} {#- Unrankable severities first, then the known ones worst first, so the first hit is always the one to put on the badge -#} {%- set ordered = (issues | reject('in', severity_levels) | sort | list) + severity_levels -%} {%- set ns = namespace(present=[]) -%} {%- for level in ordered -%} {%- if issues.get(level) -%} {%- set ns.present = ns.present + [level] -%} {%- endif -%} {%- endfor -%} {%- if not ns.present -%} {%- else -%} {#- The badge names the worst severity; the title names all of them -#} {{ ns.present[0] }} {%- endif -%} {%- endif -%} {%- endmacro %} {% macro audit_flag_detail(state, icon, ok_text, fail_text, pending_text='Not audited yet', warning_text='Weak source reference') -%} {%- if state is none -%} {{ pending_text }} {%- elif state == 2 -%} {{ warning_text }} {%- elif state -%} {{ ok_text }} {%- else -%} {{ fail_text }} {%- endif -%} {%- endmacro %} {% macro security_issues_detail(issues) -%} {%- if issues is none -%} None known yet {%- else -%} {%- set ns = namespace(any=false) -%} {%- for level in (issues | reject('in', severity_levels) | sort | list) + severity_levels -%} {%- if issues.get(level) -%} {%- set ns.any = true -%} {{ level }} {%- endif -%} {%- endfor -%} {%- if not ns.any -%} None known {%- endif -%} {%- endif -%} {%- endmacro %} {# The audit indicators get their own box inside Product Information, with a help button opening the shared #supplyChainInfoModal defined at the end of the page (one modal for the whole page - Bootstrap's data-api toggling is delegated, so it also works for the JS injected Debug/Source rows). #} {# Shown in place of nothing when the monitor has stopped because it cannot read the contract. The flags below are not cleared - they were true when they were written - so this is the only thing on the page that says how old they are. #} {% macro contract_incompatible_notice(status, compact=false) -%} {%- endmacro %} {# data-audit-box-for is how the live refresh finds this box again after the page has been served: the chain monitor rewrites these flags out of band, seconds to minutes later, and without it the only way to see the new state is a reload. See refreshAuditState() in the JS at the bottom. #} {% macro supply_chain_audit_box(build, chain_network=None) -%}
Supply Chain Audit
{%- if chain_network and chain_network.contract_status %} {{ contract_incompatible_notice(chain_network.contract_status, compact=true) }} {%- endif %}
{# Registration is the gate: the other three lines are all recorded against a registered build, so before registration they can only say "not audited yet" and are noise. State none is "not registered yet"; a false or weak (2) registration is still a registration, so those keep the full box. State 2 is only ever about the source reference. The binary checksum is the key the build was looked up under, so it is a full rpm-md digest by construction and cannot be the weak one - saying just "weak checksum" left the reader to guess which of the two. #} {%- set registered = build.registered_product is not none %}
Registered Product Build
{{ audit_flag_detail(build.registered_product, 'fa-clipboard-check', 'Registered', 'Invalid registration', 'Not registered yet', 'Registered, weak source reference') }}
{%- if registered %}
Recency
{{ audit_flag_detail(build.is_current, 'fa-flag', 'yes', 'no', 'Not audited yet') }}
Build Reproduced
{{ audit_flag_detail(build.rebuild_reproducible, 'fa-arrows-rotate', 'Reproducible', 'Not reproducible') }}
Highest Known Security Issue
{{ security_issues_detail(build.security_issues) }}
{# When the contract was last written to about this build, taken from the block its most recent event was in - nothing the contract stores carries a timestamp, so there is no other source. Distinct from the flags above in that it is a fact about the chain rather than a judgement about the build, hence the muted rendering. Unset means "no write seen", never "never written": the log feed only dates what it was watching for, plus whatever the first-run backward scan reached, so a build registered long before this instance existed can be legitimately blank. #}
Last On-Chain Write
{%- if build.last_chain_write %} {{ build.last_chain_write | int | timestamp_to_datetime }} {%- else %} Not seen yet {%- endif %}
{%- endif %}
{# Where the three flags above came from. Passed in rather than read from the context so the macro keeps working wherever it is called, and only present once the optional chain monitor has published its network, so a deployment without it looks exactly as before. #} {%- if chain_network %}
{{ chain_network.network | capitalize }} {%- if chain_network.chain_id %} (chain id {{ chain_network.chain_id }}){% endif %} · Contract: {% if chain_network.explorer_url -%} {{ chain_network.contract }} {%- else -%} {{ chain_network.contract }} {%- endif %}
{%- endif %}
{%- endmacro %} {% block extra_head %} {% endblock %} {% block content %}

Products

SPDX Product Data

Search All Packages
{% if cache_rebuilding %} {% endif %} {# Page level as well as inside each box: the mismatch is about the contract, so it affects every build on the page, and the box is only visible once a product is expanded. Not dismissible - it stays true until someone fixes the deployment. #} {% if chain_network and chain_network.contract_status %} {{ contract_incompatible_notice(chain_network.contract_status) }} {% endif %} {% if grouped_products %}

{{ grouped_products | length }} product-version(s), {{ total_product_count }} total build(s)

Loading...

Initializing search interface...

{% else %}
{% if cache_rebuilding %}

Database Rebuilding

The cache daemon is currently rebuilding the database.

Product data will appear here automatically once the SPDX scan completes.
Please wait a few minutes and refresh this page.

{% else %}

No Products Found

No SPDX product data available in cache.

Configure SPDX scanning in config.ini under [spdx] section.
Then restart the cache daemon to populate SPDX data.

{% endif %}
{% endif %}
{% endblock %}