Update templates/result.html
Browse files- templates/result.html +773 -586
templates/result.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>AI SBOM Generated</title>
|
| 7 |
-
<style>
|
| 8 |
body {
|
| 9 |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 10 |
margin: 0;
|
|
@@ -27,36 +27,71 @@
|
|
| 27 |
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
|
| 28 |
display: flex;
|
| 29 |
align-items: center;
|
|
|
|
| 30 |
margin-bottom: 30px;
|
| 31 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
.header img {
|
| 33 |
height: 60px;
|
| 34 |
margin-right: 15px;
|
| 35 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
.header h1 {
|
| 37 |
margin: 0;
|
| 38 |
font-size: 28px;
|
| 39 |
color: #2c3e50;
|
| 40 |
font-weight: 600;
|
|
|
|
| 41 |
}
|
| 42 |
-
|
| 43 |
-
/* header-content div for layout */
|
| 44 |
-
.header .header-content {
|
| 45 |
display: flex;
|
| 46 |
-
|
| 47 |
}
|
| 48 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
margin: 0;
|
| 50 |
-
font-size:
|
| 51 |
-
color: #
|
|
|
|
|
|
|
|
|
|
| 52 |
font-weight: 600;
|
| 53 |
-
|
| 54 |
}
|
| 55 |
-
/*
|
| 56 |
-
.
|
|
|
|
|
|
|
|
|
|
| 57 |
font-size: 14px;
|
| 58 |
-
|
| 59 |
-
font-weight: 500;
|
| 60 |
}
|
| 61 |
|
| 62 |
/* Content styling */
|
|
@@ -326,6 +361,19 @@
|
|
| 326 |
.score-table td {
|
| 327 |
padding: 12px;
|
| 328 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 329 |
.score-weight {
|
| 330 |
font-size: 0.9em;
|
| 331 |
color: #666;
|
|
@@ -426,6 +474,10 @@
|
|
| 426 |
color: #2e7d32;
|
| 427 |
margin-bottom: 15px;
|
| 428 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 429 |
.importance-indicator {
|
| 430 |
display: inline-block;
|
| 431 |
margin-left: 5px;
|
|
@@ -478,11 +530,11 @@
|
|
| 478 |
|
| 479 |
/* Styles for completeness profile */
|
| 480 |
.completeness-profile {
|
| 481 |
-
background-color: #
|
| 482 |
border-radius: 8px;
|
| 483 |
padding: 20px;
|
| 484 |
margin: 20px 0;
|
| 485 |
-
border-left: 4px solid #
|
| 486 |
}
|
| 487 |
.profile-badge {
|
| 488 |
display: inline-block;
|
|
@@ -547,656 +599,790 @@
|
|
| 547 |
margin-bottom: 15px;
|
| 548 |
}
|
| 549 |
|
| 550 |
-
/*
|
| 551 |
-
.
|
| 552 |
-
|
| 553 |
-
|
| 554 |
-
|
| 555 |
border-radius: 8px;
|
| 556 |
-
|
|
|
|
|
|
|
| 557 |
}
|
| 558 |
-
.
|
| 559 |
margin-top: 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 560 |
color: #2c3e50;
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
margin-bottom: 20px;
|
| 564 |
}
|
| 565 |
-
.
|
| 566 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 567 |
}
|
| 568 |
|
| 569 |
-
/*
|
| 570 |
-
.
|
| 571 |
-
|
|
|
|
| 572 |
padding: 20px;
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
|
| 576 |
}
|
| 577 |
-
|
| 578 |
-
|
| 579 |
-
|
| 580 |
-
|
| 581 |
-
|
| 582 |
-
|
| 583 |
-
|
| 584 |
-
|
| 585 |
-
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
|
| 589 |
-
|
| 590 |
-
|
| 591 |
-
|
| 592 |
-
|
| 593 |
-
|
| 594 |
-
|
| 595 |
-
|
| 596 |
-
|
| 597 |
-
|
| 598 |
-
|
| 599 |
-
}
|
| 600 |
}
|
| 601 |
</style>
|
| 602 |
</head>
|
| 603 |
<body>
|
| 604 |
-
<!-- Header with logo, title, and SBOM count -->
|
| 605 |
-
<div class="header">
|
| 606 |
-
<a href="https://aetheris.ai/" target="_blank">
|
| 607 |
-
<img src="https://huggingface.co/spaces/aetheris-ai/aibom-generator/resolve/main/templates/images/AetherisAI-logo.png" alt="Aetheris AI Logo">
|
| 608 |
-
</a>
|
| 609 |
-
<!-- Header-content div -->
|
| 610 |
-
<div class="header-content">
|
| 611 |
-
<h1>AI SBOM Generator</h1>
|
| 612 |
-
</div>
|
| 613 |
-
</div>
|
| 614 |
-
|
| 615 |
-
|
| 616 |
<div class="container">
|
| 617 |
-
|
| 618 |
-
|
| 619 |
-
|
| 620 |
-
|
| 621 |
-
|
| 622 |
-
|
| 623 |
-
<
|
| 624 |
-
|
|
|
|
| 625 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 626 |
|
| 627 |
-
|
| 628 |
-
|
| 629 |
-
|
| 630 |
-
|
| 631 |
-
<
|
| 632 |
-
<
|
| 633 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 634 |
</div>
|
| 635 |
-
{% endif %}
|
| 636 |
</div>
|
| 637 |
|
| 638 |
-
<!--
|
| 639 |
-
<div class="
|
| 640 |
-
<p><strong>
|
| 641 |
-
|
| 642 |
</div>
|
| 643 |
-
|
| 644 |
-
|
| 645 |
-
|
| 646 |
-
|
| 647 |
-
<
|
| 648 |
-
<div
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 649 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 650 |
|
| 651 |
-
|
| 652 |
-
<div class="
|
| 653 |
-
|
| 654 |
-
|
| 655 |
-
<
|
|
|
|
|
|
|
|
|
|
| 656 |
<div class="aibom-property">
|
| 657 |
-
<
|
| 658 |
-
<
|
| 659 |
</div>
|
| 660 |
<div class="aibom-property">
|
| 661 |
-
<
|
| 662 |
-
<
|
| 663 |
</div>
|
| 664 |
<div class="aibom-property">
|
| 665 |
-
<
|
| 666 |
-
<
|
| 667 |
</div>
|
| 668 |
<div class="aibom-property">
|
| 669 |
-
<
|
| 670 |
-
<
|
| 671 |
</div>
|
| 672 |
-
{% if aibom.components and aibom.components[0].
|
| 673 |
<div class="aibom-property">
|
| 674 |
-
<
|
| 675 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
| 676 |
</div>
|
| 677 |
{% endif %}
|
| 678 |
</div>
|
| 679 |
|
| 680 |
-
<!-- Model Card Section -->
|
| 681 |
{% if aibom.components and aibom.components[0].modelCard %}
|
| 682 |
<div class="aibom-section">
|
| 683 |
-
<h4
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
<
|
| 687 |
-
|
| 688 |
-
<div class="property-value">
|
| 689 |
-
<ul>
|
| 690 |
-
{% for key, value in aibom.components[0].modelCard.modelParameters.items() %}
|
| 691 |
-
<li><strong>{{ key }}:</strong> {{ value }}</li>
|
| 692 |
-
{% endfor %}
|
| 693 |
-
</ul>
|
| 694 |
-
</div>
|
| 695 |
-
</div>
|
| 696 |
-
{% endif %}
|
| 697 |
-
|
| 698 |
-
{% if aibom.components[0].modelCard.considerations %}
|
| 699 |
-
<div class="aibom-property">
|
| 700 |
-
<div class="property-name">Considerations:</div>
|
| 701 |
-
<div class="property-value">
|
| 702 |
-
<ul>
|
| 703 |
-
{% for key, value in aibom.components[0].modelCard.considerations.items() %}
|
| 704 |
-
<li><strong>{{ key }}:</strong> {{ value }}</li>
|
| 705 |
-
{% endfor %}
|
| 706 |
-
</ul>
|
| 707 |
-
</div>
|
| 708 |
-
</div>
|
| 709 |
-
{% endif %}
|
| 710 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 711 |
</div>
|
| 712 |
{% endif %}
|
| 713 |
-
|
| 714 |
-
|
| 715 |
-
{% if aibom.components and aibom.components[0].externalReferences %}
|
| 716 |
<div class="aibom-section">
|
| 717 |
-
<h4
|
| 718 |
-
|
| 719 |
-
|
| 720 |
-
|
| 721 |
-
|
| 722 |
-
<strong>{{ ref.type }}:</strong>
|
| 723 |
-
<a href="{{ ref.url }}" target="_blank">{{ ref.url }}</a>
|
| 724 |
-
{% if ref.comment %}
|
| 725 |
-
<br><em>{{ ref.comment }}</em>
|
| 726 |
-
{% endif %}
|
| 727 |
-
</li>
|
| 728 |
-
{% endfor %}
|
| 729 |
-
</ul>
|
| 730 |
</div>
|
|
|
|
| 731 |
</div>
|
| 732 |
{% endif %}
|
| 733 |
-
</div>
|
| 734 |
-
</div>
|
| 735 |
|
| 736 |
-
|
| 737 |
-
|
| 738 |
-
|
| 739 |
-
|
| 740 |
-
|
| 741 |
-
|
| 742 |
-
<div id="field-checklist" class="tab-content">
|
| 743 |
-
<div class="content-section">
|
| 744 |
-
<h3>Field Checklist & Mapping</h3>
|
| 745 |
-
|
| 746 |
-
<!-- Field Tier Legend -->
|
| 747 |
-
<div class="tier-legend">
|
| 748 |
-
<div class="tier-legend-item">
|
| 749 |
-
<span class="field-tier tier-critical"></span>
|
| 750 |
-
<span>Critical</span>
|
| 751 |
</div>
|
| 752 |
-
<div class="
|
| 753 |
-
<span class="
|
| 754 |
-
<span>
|
| 755 |
</div>
|
| 756 |
-
|
| 757 |
-
|
| 758 |
-
<span>
|
|
|
|
| 759 |
</div>
|
|
|
|
| 760 |
</div>
|
| 761 |
-
|
| 762 |
-
<p>This table shows how fields map to the CycloneDX specification and their status in your AI SBOM.</p>
|
| 763 |
-
|
| 764 |
-
<div class="field-mapping-container">
|
| 765 |
-
<h4>Standard CycloneDX Fields</h4>
|
| 766 |
-
<p>These fields are part of the official CycloneDX specification and are used in all SBOMs:</p>
|
| 767 |
-
<table class="field-mapping-table">
|
| 768 |
-
<thead>
|
| 769 |
-
<tr>
|
| 770 |
-
<th>Status</th>
|
| 771 |
-
<th>Field Name</th>
|
| 772 |
-
<th>CycloneDX JSON Path</th>
|
| 773 |
-
<th>Info</th>
|
| 774 |
-
<th>Importance</th>
|
| 775 |
-
</tr>
|
| 776 |
-
</thead>
|
| 777 |
-
<tbody>
|
| 778 |
-
{% for field_key, field_data in completeness_score.field_categorization.standard_cyclonedx_fields.items() %}
|
| 779 |
-
<tr class="{% if field_data.status == '✔' %}present-field{% else %}missing-field{% endif %}">
|
| 780 |
-
<td class="status-cell">
|
| 781 |
-
{% if field_data.status == "✔" %}
|
| 782 |
-
<span class="check-mark">✔</span>
|
| 783 |
-
{% else %}
|
| 784 |
-
<span class="x-mark">✘</span>
|
| 785 |
-
{% endif %}
|
| 786 |
-
</td>
|
| 787 |
-
<td>{{ field_data.field_name }}</td>
|
| 788 |
-
<td>{{ field_data.json_path }}</td>
|
| 789 |
-
<td>
|
| 790 |
-
<span class="tooltip">(?)
|
| 791 |
-
<span class="tooltiptext">{{ field_data.field_name }} field information.</span>
|
| 792 |
-
</span>
|
| 793 |
-
</td>
|
| 794 |
-
<td>
|
| 795 |
-
<span class="field-tier tier-{{ field_data.importance|lower }}"></span>
|
| 796 |
-
{{ field_data.importance }}
|
| 797 |
-
</td>
|
| 798 |
-
</tr>
|
| 799 |
-
{% endfor %}
|
| 800 |
-
</tbody>
|
| 801 |
-
</table>
|
| 802 |
|
| 803 |
-
|
| 804 |
-
|
| 805 |
-
|
| 806 |
-
|
| 807 |
-
|
| 808 |
-
|
| 809 |
-
|
| 810 |
-
|
| 811 |
-
|
| 812 |
-
|
| 813 |
-
|
| 814 |
-
|
| 815 |
-
|
| 816 |
-
|
| 817 |
-
|
| 818 |
-
|
| 819 |
-
|
| 820 |
-
|
| 821 |
-
|
| 822 |
-
|
| 823 |
-
|
| 824 |
-
|
| 825 |
-
|
| 826 |
-
|
| 827 |
-
|
| 828 |
-
<td>
|
| 829 |
-
<span class="tooltip">(?)
|
| 830 |
-
<span class="tooltiptext">{{ field_data.field_name }} field information.</span>
|
| 831 |
-
</span>
|
| 832 |
-
</td>
|
| 833 |
-
<td>
|
| 834 |
-
<span class="field-tier tier-{{ field_data.importance|lower }}"></span>
|
| 835 |
-
{{ field_data.importance }}
|
| 836 |
-
</td>
|
| 837 |
-
</tr>
|
| 838 |
-
{% endfor %}
|
| 839 |
-
</tbody>
|
| 840 |
-
</table>
|
| 841 |
-
</div>
|
| 842 |
-
|
| 843 |
-
<style>
|
| 844 |
-
.field-mapping-container {
|
| 845 |
-
margin-top: 20px;
|
| 846 |
-
max-width: 100%;
|
| 847 |
-
overflow-x: auto;
|
| 848 |
-
}
|
| 849 |
-
.field-mapping-table {
|
| 850 |
-
width: 100%;
|
| 851 |
-
border-collapse: collapse;
|
| 852 |
-
margin-bottom: 30px;
|
| 853 |
-
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
| 854 |
-
border-radius: 8px;
|
| 855 |
-
overflow: hidden;
|
| 856 |
-
table-layout: fixed;
|
| 857 |
-
}
|
| 858 |
-
.field-mapping-table th {
|
| 859 |
-
background-color: #f5f5f5;
|
| 860 |
-
padding: 12px 15px;
|
| 861 |
-
text-align: left;
|
| 862 |
-
font-weight: 600;
|
| 863 |
-
color: #333;
|
| 864 |
-
border-bottom: 2px solid #ddd;
|
| 865 |
-
}
|
| 866 |
-
.field-mapping-table td {
|
| 867 |
-
padding: 10px 15px;
|
| 868 |
-
border-bottom: 1px solid #eee;
|
| 869 |
-
vertical-align: middle;
|
| 870 |
-
word-wrap: break-word;
|
| 871 |
-
word-break: break-word;
|
| 872 |
-
max-width: 250px;
|
| 873 |
-
}
|
| 874 |
-
.field-mapping-table tr:last-child td {
|
| 875 |
-
border-bottom: none;
|
| 876 |
-
}
|
| 877 |
-
.field-mapping-table tr:hover {
|
| 878 |
-
background-color: #f9f9f9;
|
| 879 |
-
}
|
| 880 |
-
.status-cell {
|
| 881 |
-
text-align: center;
|
| 882 |
-
width: 60px;
|
| 883 |
-
}
|
| 884 |
-
.present-field {
|
| 885 |
-
background-color: #f0f7f0;
|
| 886 |
-
}
|
| 887 |
-
.missing-field {
|
| 888 |
-
background-color: #fff7f7;
|
| 889 |
-
}
|
| 890 |
-
.check-mark {
|
| 891 |
-
color: #4caf50;
|
| 892 |
-
font-weight: bold;
|
| 893 |
-
font-size: 18px;
|
| 894 |
-
}
|
| 895 |
-
.x-mark {
|
| 896 |
-
color: #f44336;
|
| 897 |
-
font-weight: bold;
|
| 898 |
-
font-size: 18px;
|
| 899 |
-
}
|
| 900 |
-
</style>
|
| 901 |
</div>
|
| 902 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 903 |
|
| 904 |
-
|
| 905 |
-
<div class="
|
| 906 |
-
<
|
| 907 |
-
|
| 908 |
-
|
| 909 |
-
|
| 910 |
-
|
| 911 |
-
|
| 912 |
-
|
| 913 |
-
|
| 914 |
-
|
| 915 |
-
|
| 916 |
-
|
| 917 |
-
|
| 918 |
-
|
| 919 |
-
|
| 920 |
-
|
| 921 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 922 |
</div>
|
| 923 |
-
|
| 924 |
-
|
| 925 |
-
|
| 926 |
-
|
| 927 |
-
|
| 928 |
-
|
| 929 |
-
|
| 930 |
-
|
| 931 |
-
|
| 932 |
-
|
| 933 |
-
|
| 934 |
-
|
| 935 |
-
|
| 936 |
-
|
| 937 |
-
|
| 938 |
-
|
| 939 |
-
|
| 940 |
-
|
| 941 |
-
|
| 942 |
-
|
| 943 |
-
|
| 944 |
-
|
| 945 |
-
|
| 946 |
-
|
| 947 |
-
|
| 948 |
-
|
| 949 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 950 |
</div>
|
| 951 |
-
|
| 952 |
-
|
| 953 |
-
|
| 954 |
-
|
| 955 |
-
|
| 956 |
-
|
| 957 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 958 |
</div>
|
| 959 |
-
|
| 960 |
-
|
| 961 |
-
|
| 962 |
-
|
|
|
|
|
|
|
| 963 |
<thead>
|
| 964 |
<tr>
|
| 965 |
-
<th>
|
| 966 |
-
<th>
|
| 967 |
-
<th>
|
| 968 |
-
<th>
|
|
|
|
| 969 |
</tr>
|
| 970 |
</thead>
|
| 971 |
<tbody>
|
| 972 |
-
{% set
|
| 973 |
-
{%
|
| 974 |
-
|
| 975 |
-
|
| 976 |
-
|
| 977 |
-
|
| 978 |
-
|
| 979 |
-
|
| 980 |
-
|
| 981 |
-
|
| 982 |
-
|
| 983 |
-
|
| 984 |
-
|
| 985 |
-
|
| 986 |
-
|
| 987 |
-
|
| 988 |
-
|
| 989 |
-
|
| 990 |
-
|
| 991 |
-
|
| 992 |
-
|
| 993 |
-
</span>
|
| 994 |
-
</td>
|
| 995 |
-
<td>{{ score|round(1) }}/{{ completeness_score.max_scores[section] }}</td>
|
| 996 |
-
<td>{{ weights[section] }}%</td>
|
| 997 |
-
<td style="width: 50%;">
|
| 998 |
-
<div class="progress-container">
|
| 999 |
-
{% set percent = (score / completeness_score.max_scores[section]) * 100 %}
|
| 1000 |
-
{% set class = 'progress-poor' %}
|
| 1001 |
-
|
| 1002 |
-
{% if percent >= 90 %}
|
| 1003 |
-
{% set class = 'progress-excellent' %}
|
| 1004 |
-
{% elif percent >= 70 %}
|
| 1005 |
-
{% set class = 'progress-good' %}
|
| 1006 |
-
{% elif percent >= 50 %}
|
| 1007 |
-
{% set class = 'progress-fair' %}
|
| 1008 |
-
{% endif %}
|
| 1009 |
-
|
| 1010 |
-
<div class="progress-bar {{ class }}" style="width: {{ percent }}%">
|
| 1011 |
-
{{ percent|int }}%
|
| 1012 |
-
</div>
|
| 1013 |
-
</div>
|
| 1014 |
-
</td>
|
| 1015 |
-
</tr>
|
| 1016 |
{% endfor %}
|
| 1017 |
</tbody>
|
| 1018 |
</table>
|
| 1019 |
-
|
| 1020 |
-
|
| 1021 |
-
|
| 1022 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1023 |
|
| 1024 |
-
<!--
|
| 1025 |
-
<div class="
|
| 1026 |
-
<
|
| 1027 |
-
<
|
| 1028 |
-
|
| 1029 |
-
|
| 1030 |
-
|
| 1031 |
-
|
| 1032 |
-
{%
|
| 1033 |
-
|
| 1034 |
-
|
| 1035 |
-
|
| 1036 |
-
|
| 1037 |
-
|
| 1038 |
-
|
| 1039 |
-
|
| 1040 |
-
|
| 1041 |
-
|
| 1042 |
-
- Add model parameters section with architecture, size, and training details
|
| 1043 |
-
{% elif field == "primaryPurpose" %}
|
| 1044 |
-
- Add primary purpose information (what the model is designed for)
|
| 1045 |
-
{% else %}
|
| 1046 |
-
- This field is required for comprehensive documentation
|
| 1047 |
-
{% endif %}
|
| 1048 |
-
</li>
|
| 1049 |
-
{% endif %}
|
| 1050 |
{% endif %}
|
| 1051 |
-
|
| 1052 |
-
|
| 1053 |
-
|
| 1054 |
-
|
| 1055 |
-
|
| 1056 |
-
|
| 1057 |
-
|
| 1058 |
-
<!-- Recommendations Section -->
|
| 1059 |
-
<div class="calculation-section recommendations">
|
| 1060 |
-
<h4>Recommendations to Improve Your Score</h4>
|
| 1061 |
-
<ol>
|
| 1062 |
-
{% if completeness_score.section_scores.component_model_card < completeness_score.max_scores.component_model_card %}
|
| 1063 |
-
<li>
|
| 1064 |
-
<strong>Enhance Model Card</strong> (+{{ ((completeness_score.max_scores.component_model_card - completeness_score.section_scores.component_model_card) * 0.3)|round(1) }} points):
|
| 1065 |
-
<ul>
|
| 1066 |
-
{% if completeness_score.missing_fields.critical %}
|
| 1067 |
-
{% for field in completeness_score.missing_fields.critical %}
|
| 1068 |
-
{% if field == "modelCard.modelParameters" or field == "modelCard.considerations" %}
|
| 1069 |
-
<li>Add {{ field }} information</li>
|
| 1070 |
-
{% endif %}
|
| 1071 |
-
{% endfor %}
|
| 1072 |
-
{% endif %}
|
| 1073 |
-
</ul>
|
| 1074 |
-
</li>
|
| 1075 |
-
{% endif %}
|
| 1076 |
-
|
| 1077 |
-
{% if completeness_score.section_scores.component_basic < completeness_score.max_scores.component_basic %}
|
| 1078 |
-
<li>
|
| 1079 |
-
<strong>Add Basic Component Information</strong> (+{{ ((completeness_score.max_scores.component_basic - completeness_score.section_scores.component_basic) * 0.2)|round(1) }} points):
|
| 1080 |
-
<ul>
|
| 1081 |
-
{% if completeness_score.missing_fields.critical %}
|
| 1082 |
-
{% for field in completeness_score.missing_fields.critical %}
|
| 1083 |
-
{% if field == "name" or field == "description" or field == "purl" %}
|
| 1084 |
-
<li>Add {{ field }} information</li>
|
| 1085 |
-
{% endif %}
|
| 1086 |
-
{% endfor %}
|
| 1087 |
-
{% endif %}
|
| 1088 |
-
{% if completeness_score.missing_fields.important %}
|
| 1089 |
-
{% for field in completeness_score.missing_fields.important %}
|
| 1090 |
-
{% if field == "type" or field == "licenses" %}
|
| 1091 |
-
<li>Add {{ field }} information</li>
|
| 1092 |
-
{% endif %}
|
| 1093 |
-
{% endfor %}
|
| 1094 |
-
{% endif %}
|
| 1095 |
-
</ul>
|
| 1096 |
-
</li>
|
| 1097 |
-
{% endif %}
|
| 1098 |
-
|
| 1099 |
-
{% if completeness_score.section_scores.metadata < completeness_score.max_scores.metadata %}
|
| 1100 |
-
<li>
|
| 1101 |
-
<strong>Add Metadata</strong> (+{{ ((completeness_score.max_scores.metadata - completeness_score.section_scores.metadata) * 0.2)|round(1) }} points):
|
| 1102 |
-
<ul>
|
| 1103 |
-
{% if completeness_score.missing_fields.critical %}
|
| 1104 |
-
{% for field in completeness_score.missing_fields.critical %}
|
| 1105 |
-
{% if field == "primaryPurpose" or field == "suppliedBy" %}
|
| 1106 |
-
<li>Add {{ field }} information</li>
|
| 1107 |
-
{% endif %}
|
| 1108 |
-
{% endfor %}
|
| 1109 |
-
{% endif %}
|
| 1110 |
-
{% if completeness_score.missing_fields.supplementary %}
|
| 1111 |
-
{% for field in completeness_score.missing_fields.supplementary %}
|
| 1112 |
-
{% if field == "standardCompliance" or field == "domain" or field == "autonomyType" %}
|
| 1113 |
-
<li>Add {{ field }} information</li>
|
| 1114 |
-
{% endif %}
|
| 1115 |
-
{% endfor %}
|
| 1116 |
-
{% endif %}
|
| 1117 |
-
</ul>
|
| 1118 |
-
</li>
|
| 1119 |
-
{% endif %}
|
| 1120 |
-
|
| 1121 |
-
{% if completeness_score.section_scores.external_references < completeness_score.max_scores.external_references %}
|
| 1122 |
-
<li>
|
| 1123 |
-
<strong>Add External References</strong> (+{{ ((completeness_score.max_scores.external_references - completeness_score.section_scores.external_references) * 0.1)|round(1) }} points):
|
| 1124 |
-
<ul>
|
| 1125 |
-
{% if completeness_score.missing_fields.critical %}
|
| 1126 |
-
{% for field in completeness_score.missing_fields.critical %}
|
| 1127 |
-
{% if field == "downloadLocation" %}
|
| 1128 |
-
<li>Add download location reference</li>
|
| 1129 |
-
{% endif %}
|
| 1130 |
-
{% endfor %}
|
| 1131 |
-
{% endif %}
|
| 1132 |
-
<li>Add links to model card, repository, and dataset</li>
|
| 1133 |
-
</ul>
|
| 1134 |
-
</li>
|
| 1135 |
-
{% endif %}
|
| 1136 |
-
|
| 1137 |
-
{% if completeness_score.validation and not completeness_score.validation.valid %}
|
| 1138 |
-
<li>
|
| 1139 |
-
<strong>Fix Validation Issues</strong> (remove validation penalty):
|
| 1140 |
-
<ul>
|
| 1141 |
-
{% for recommendation in completeness_score.validation.recommendations %}
|
| 1142 |
-
<li>{{ recommendation }}</li>
|
| 1143 |
-
{% endfor %}
|
| 1144 |
-
</ul>
|
| 1145 |
-
</li>
|
| 1146 |
-
{% endif %}
|
| 1147 |
-
</ol>
|
| 1148 |
</div>
|
| 1149 |
-
|
| 1150 |
-
<!-- Scoring
|
| 1151 |
-
<div class="
|
| 1152 |
-
<h4>
|
| 1153 |
-
<p>The
|
| 1154 |
-
<p><strong>Total Score = Sum of (Section Score × Section Weight)</strong></p>
|
| 1155 |
-
<p>Where:</p>
|
| 1156 |
<ul>
|
| 1157 |
-
<li>
|
| 1158 |
-
<li>
|
|
|
|
|
|
|
|
|
|
| 1159 |
</ul>
|
| 1160 |
|
| 1161 |
-
<
|
| 1162 |
-
|
| 1163 |
-
|
| 1164 |
-
|
| 1165 |
-
|
| 1166 |
-
|
| 1167 |
-
<li>Model Card: 10 points × 0.30 weight = 3.0 points</li>
|
| 1168 |
-
<li>External References: 5 points × 0.10 weight = 0.5 points</li>
|
| 1169 |
-
</ul>
|
| 1170 |
-
<p>The total score would be 12.5 points, even though the raw section scores sum to 60 points.</p>
|
| 1171 |
-
<p><strong>Note:</strong> The total score is <em>not</em> the sum of section scores. Each section contributes proportionally to its weight in the final score.</p>
|
| 1172 |
-
</div>
|
| 1173 |
-
|
| 1174 |
-
<p>Fields are classified into three tiers based on importance:</p>
|
| 1175 |
<ul>
|
| 1176 |
-
<li
|
| 1177 |
-
<li
|
| 1178 |
-
<li
|
| 1179 |
</ul>
|
| 1180 |
|
| 1181 |
-
<p>
|
| 1182 |
<ul>
|
| 1183 |
-
<li>
|
| 1184 |
-
<li>
|
| 1185 |
-
<li>Missing >5 important fields: 5% penalty (score × 0.95)</li>
|
| 1186 |
</ul>
|
| 1187 |
|
| 1188 |
-
|
| 1189 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1190 |
<ul>
|
| 1191 |
-
<li>
|
| 1192 |
-
<li>
|
|
|
|
| 1193 |
</ul>
|
|
|
|
|
|
|
|
|
|
| 1194 |
{% endif %}
|
| 1195 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1196 |
</div>
|
| 1197 |
</div>
|
| 1198 |
</div>
|
| 1199 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1200 |
<div class="content-section" style="text-align: center;">
|
| 1201 |
<h3>🗣️ Help Us Spread the Word</h3>
|
| 1202 |
<p>If you find this tool useful, share it with your network! <a href="https://sbom.aetheris.ai" target="_blank" rel="noopener noreferrer">https://sbom.aetheris.ai</a></p>
|
|
@@ -1209,17 +1395,17 @@
|
|
| 1209 |
</p>
|
| 1210 |
</div>
|
| 1211 |
|
| 1212 |
-
|
| 1213 |
-
<div class="content-section" style="text-align: center
|
| 1214 |
<!-- Display the SBOM count -->
|
| 1215 |
<div class="sbom-count">🚀 Generated AI SBOMs using this tool: <strong>{{ sbom_count if sbom_count else 'N/A' }}</strong></div>
|
| 1216 |
</div>
|
| 1217 |
-
|
| 1218 |
<!-- Footer -->
|
| 1219 |
<div class="footer">
|
| 1220 |
<p>© 2025 AI SBOM Generator | Powered by Aetheris AI</p>
|
| 1221 |
</div>
|
| 1222 |
-
|
| 1223 |
|
| 1224 |
<script>
|
| 1225 |
function switchTab(tabId) {
|
|
@@ -1272,4 +1458,5 @@
|
|
| 1272 |
});
|
| 1273 |
</script>
|
| 1274 |
</body>
|
| 1275 |
-
</html>
|
|
|
|
|
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>AI SBOM Generated</title>
|
| 7 |
+
<script type="text/javascript" src="https://gc.kis.v2.scr.kaspersky-labs.com/FD126C42-EBFA-4E12-B309-BB3FDD723AC1/main.js?attr=tvQoyfSXq4JVDJvyoOAfThXMw9mgZRducLzTjUOnVphMAP2MBTXzDKF8WIUJETdEqCHXbUfgy-ihVF7QjtQfVIhhPZixhTUykm7ogEKcAY8g8XaCJjgLJ20ey7kvNW5yNFjtTgdjbiRHA4-4FfeZelCLWCOSbbpWpDquPezYp8V_SOTuYVK6EghRcNZgchGXWWoSOoga9DiwoB_4FVDoLZLAdtsEBybX-rcletazWXVi9vxFurtEiSBk3ewixUb_l1FR4W7mdhQXaDegmrEu__o1qNa73vqLlLY22wmjB5rhQnOItFstTw-BRsUtYRbY7d-jjDlvtLjvqrwMm8rYZlFzpvbgjkeQzbbyXQy0Wd0YNm11gR1z-q0xI-BTRItFmStcjfEWzrsnhOWvBeHrGvEpX8yWcLTOAOHXrE6Cp-i3mThNUiOErT99ZiPPmhieQZl6oq1Ed3sSldNMH1hsMsKuGxs-FhkmukdqA7jGa4gLoH44TqKyiB9xYz9SYuz02ngy3Z_jH7YuKbVCIqs3_GoXzOcbdzr0fRyP6CTomcBrIoSZQEx7ViPv0Lp4wf3pPt_zyOSVCeQ5kf3vjTsS-_0fs5KrbHNv79lNkBALSrNDDJTBFTo7RboIfhfsRdK0mZXAwzUgMuQVQSTVfe38SAk81t5hep59Nt9DAPECVEYO1j8YUeSPMHfFOcMXU8Jf2pWawwZYjHry6zfQ9Lf7gr-4QPIIvNjN_0kEGt6x-V8_QriVH4z1LkeLkLsy8a_i95Z5CadplFml5XZnt_MAi9rOfF1SVGfUjKYelOg1hUTRfDmFyHR4V1RCVJvdXCY17EHPfT7r0V6TUWFNhWAK2dkA8Be-CH_sb0LcyK1nb4zXrMlOQIB-XMsPxVl_tE3jLRTn9DREQDPnQ2G1-KeyjdI9zyutUVukG3EAdmJ-mH-9ATWfGuZQpRxblkXPiq4Ssi6jYLmE9yLcJyyZ3IfDsEMq4ZF7hNIutja3YPlCNUnE1U1yxqcNZvodlEKoTBpE0eZmq1_VVvZZmADz2CY6ZGrMMLb4-JPFw6mY8Y6sWSIuVok5nId4MmVrvMjf_M0DdPkRyCsqNBfw89fUFjUGWe6N0TTU4r595mfdPEg4HJJsq7qRlMCp3n1K8xMbz3zJDHe0OW-9_TcA7dSK7WpxkX8gaXemJddZjRuqJEIo4U5ortUQxCgYREMUAHYnWNZzy0qiyKYR17bA4apHq40wF3L-D_NUKkCP_i08dsCEabPqDHWM2HGW04kchwOlVcZeMKM592clkn4Fv6eIioqQIbFhFjAdnPiqSm4xWNtQxVn6VusRr4Sah0Vw5WYWaBqcZ4sJiQ6OslO0HKY8rg4MO6xo8niPr2tn9V_qwCIPLfYXfgub5tEofKtQkChKgIhtY8HIkFF25ZRyQf-MBu-bOfEG6WSBiuAqm25MqU00kqMHmv-y8tORjPhwHfl78Z1U0w3bz1NUoWtzB_qKFL1aCR6K0B2I59gS2ZvIj5BBM0rz0_u2QuogHNq1HluUEq6GkefCTZI8ovLHPFSVqWkQxqmvs7w3l2P3b9wXGzvnTR01bEVDNUETDHsDO9faiPkKoBS_vOwHNlJEJdPhfIpULJ0VgULPBrfN3XtHk14dcEGcXaFwIfXjeDMs5RXb38hs0wCmXcFQlr0TxIQ5t8jPMef3zCKlqqHm2l1HtJQJfzAOxbxZ2DQ6-LaeGBgHE6iW" nonce="508f6bedf744be51dd051f51433cdbea" charset="UTF-8"></script><link rel="stylesheet" crossorigin="anonymous" href="https://gc.kis.v2.scr.kaspersky-labs.com/E3E8934C-235A-4B0E-825A-35A08381A191/abn/main.css?attr=aHR0cHM6Ly9tYWlsLWF0dGFjaG1lbnQuZ29vZ2xldXNlcmNvbnRlbnQuY29tL2F0dGFjaG1lbnQvdS8wLz91aT0yJmlrPTI5MzQwOTYwNGImYXR0aWQ9MC4xJnBlcm1tc2dpZD1tc2ctZjoxODM1MTQzNjcwMjEyNTQ2MDM4JnRoPTE5NzdiZDcxZWVkMzRkZjYmdmlldz1hdHQmZGlzcD1zYWZlJnJlYWxhdHRpZD1mX21ienh0cTdrMCZ6dyZzYWRkYmF0PUFOR2pkSjlXOXNjTFh3Q0hueU9Bd0VFcFlrYUNSSDd4dFlPUFBYd0p6VndUbHZuLUhxTjMtSTFwOVk0d0tCMU10YWxVcTBWeW03TUJKWGVfcGNwa1kxVkowTjFmQTZqM2xUSm9nZlNPQ0FqcGtzSHROS0tBTXRtQ1ZqYTFnWkhPZUNfNWU0T3ExcFQxdUF2WE9kb19neDBxMlFMQnJMSnNobWQxZGd4RjY1MjdRRUxkUUlWRm0xY3V3Q1RlVGREWnlxYjZtdDdBcUI4UTJhdlJGaFRkUTE5eEx2QlFzOFJ2cXgxeDY5Y09mUjFmYlJpb2s3VzQ5TFp4eVY5T05pbVdyZHRnZ3d5Y1NfY2I0SkNveXRhXzd5d2NDamVpQmxaTGlMLUg1LU5DNTQ1TjhSZVNZVWRkeTJCSExzaFg4a2xLejdwaG04SVBPTlB4YzhsTk5TVjN1TkZlTTVrdWpSNUYxM0RJMjVWZ184ZEY3eGtDeENKYnk4QVBiTkpYVW5sOHlmZWR3b0FqTmtOU0taZTRRaHRsMnBFbWhBNU9DQTM1eUpKcGxFMEEzM1VweE41WFNxM2pRdFZrZDlFckllNnNWcUEtWjRSbGVuaEFJNG03Q3J3ZXctSjhjbllXN2NuZVJuaHoySWtkNkdhdVFubzRmOUxYV25wUnZsTkpVdTVTV2VDanZtRmtZOUJ0UVFjNGFCZHBiMEdIMkNIOXFZM1JxOEhOVTltN040ZUJKdUJLT2lIMUJEaVFWNFdHa052YW9INEdJYXRSRmFWYzBXcGFubERWblJnZS1GNzdvMkJSY1FpQkIzMVdFM0pxN3ZDRDlYSVoxckJNZnNzdGhnNEcxUGliNC1jSk1FakNJUWE0SDVQZUFCYUt6R0xpRVRNRWp1cFFXVWJJV3ZJMktOdHpEd04wQkpWcjVrM20zQ19qMl9ady1Qd296VG1qbjA5X1ZOdzlOSERyeGd2VnZxR01GQ3JDRHpQX1lNNnhhRlM4Tk82bDc0LVByNVZUYlIzQTJGdlhlVTJSRWIzMGV3NDlYUGM0VDYyLTUwRkstM3dySFlNNmtTQ3l4ZXJYNXBZbmxpOWZlRlU1blpzTFQ0dENyOGx5R0FReVJ1ZEpBTVl6YnNzai1pdjZXMk5wNmFRWDZZNktfZ1l4VmtPTWU1bzctMWdiTTFfWG5lMklNZl83dE5oTERLNTFPMTBNWHZYTWJOblhaNjhEOGpCMmFhdHhfaHlFbEtSb0RMU05KTHJuMVJlY0xGMy1Nb1hMLVNQVFM2MlNhdUV5RGxoNDZ0T3p2TUJPeG95UjF4TEI0OWVOSWJkODBidVprY1BLQ1ZNUmI2OTNGVUQ3eHowZ3h3c1lWRTZsOTI3MXlOUml6MHRBX1BuSk4zbEZkTUkzNy1pQjJSTlFDV0ZYVHc"/><style>
|
| 8 |
body {
|
| 9 |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 10 |
margin: 0;
|
|
|
|
| 27 |
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
|
| 28 |
display: flex;
|
| 29 |
align-items: center;
|
| 30 |
+
justify-content: space-between;
|
| 31 |
margin-bottom: 30px;
|
| 32 |
}
|
| 33 |
+
.header-left {
|
| 34 |
+
display: flex;
|
| 35 |
+
align-items: center;
|
| 36 |
+
}
|
| 37 |
.header img {
|
| 38 |
height: 60px;
|
| 39 |
margin-right: 15px;
|
| 40 |
}
|
| 41 |
+
.header-content {
|
| 42 |
+
display: flex;
|
| 43 |
+
flex-direction: column;
|
| 44 |
+
}
|
| 45 |
.header h1 {
|
| 46 |
margin: 0;
|
| 47 |
font-size: 28px;
|
| 48 |
color: #2c3e50;
|
| 49 |
font-weight: 600;
|
| 50 |
+
margin-bottom: 5px;
|
| 51 |
}
|
| 52 |
+
.header-right {
|
|
|
|
|
|
|
| 53 |
display: flex;
|
| 54 |
+
gap: 10px;
|
| 55 |
}
|
| 56 |
+
.generate-another-btn {
|
| 57 |
+
padding: 12px 20px;
|
| 58 |
+
background-color: #3498db;
|
| 59 |
+
color: white;
|
| 60 |
+
text-decoration: none;
|
| 61 |
+
border-radius: 6px;
|
| 62 |
+
font-weight: 500;
|
| 63 |
+
font-size: 15px;
|
| 64 |
+
transition: background-color 0.3s;
|
| 65 |
+
}
|
| 66 |
+
.generate-another-btn:hover {
|
| 67 |
+
background-color: #2980b9;
|
| 68 |
+
text-decoration: none;
|
| 69 |
+
}
|
| 70 |
+
.success-message {
|
| 71 |
+
text-align: left;
|
| 72 |
+
padding: 15px;
|
| 73 |
+
background-color: #d4edda;
|
| 74 |
+
border: 1px solid #c3e6cb;
|
| 75 |
+
border-radius: 8px;
|
| 76 |
+
margin-bottom: 20px;
|
| 77 |
+
}
|
| 78 |
+
.success-message h2 {
|
| 79 |
margin: 0;
|
| 80 |
+
font-size: 18px;
|
| 81 |
+
color: #155724;
|
| 82 |
+
font-weight: 500;
|
| 83 |
+
}
|
| 84 |
+
.model-name {
|
| 85 |
font-weight: 600;
|
| 86 |
+
color: #2c3e50;
|
| 87 |
}
|
| 88 |
+
/* Footer styling */
|
| 89 |
+
.footer {
|
| 90 |
+
text-align: center;
|
| 91 |
+
padding: 20px;
|
| 92 |
+
color: #7f8c8d;
|
| 93 |
font-size: 14px;
|
| 94 |
+
margin-top: 30px;
|
|
|
|
| 95 |
}
|
| 96 |
|
| 97 |
/* Content styling */
|
|
|
|
| 361 |
.score-table td {
|
| 362 |
padding: 12px;
|
| 363 |
}
|
| 364 |
+
/* Adjust column widths for better progress bar display */
|
| 365 |
+
.score-table th:nth-child(1), .score-table td:nth-child(1) {
|
| 366 |
+
width: 25%; /* Category column */
|
| 367 |
+
}
|
| 368 |
+
.score-table th:nth-child(2), .score-table td:nth-child(2) {
|
| 369 |
+
width: 20%; /* Fields Present column */
|
| 370 |
+
}
|
| 371 |
+
.score-table th:nth-child(3), .score-table td:nth-child(3) {
|
| 372 |
+
width: 15%; /* Score column */
|
| 373 |
+
}
|
| 374 |
+
.score-table th:nth-child(4), .score-table td:nth-child(4) {
|
| 375 |
+
width: 40%; /* Progress column - wider for better display */
|
| 376 |
+
}
|
| 377 |
.score-weight {
|
| 378 |
font-size: 0.9em;
|
| 379 |
color: #666;
|
|
|
|
| 474 |
color: #2e7d32;
|
| 475 |
margin-bottom: 15px;
|
| 476 |
}
|
| 477 |
+
.recommendations ul {
|
| 478 |
+
margin-bottom: 0;
|
| 479 |
+
padding-left: 20px;
|
| 480 |
+
}
|
| 481 |
.importance-indicator {
|
| 482 |
display: inline-block;
|
| 483 |
margin-left: 5px;
|
|
|
|
| 530 |
|
| 531 |
/* Styles for completeness profile */
|
| 532 |
.completeness-profile {
|
| 533 |
+
background-color: #f6f5f5;
|
| 534 |
border-radius: 8px;
|
| 535 |
padding: 20px;
|
| 536 |
margin: 20px 0;
|
| 537 |
+
border-left: 4px solid #7f7c7c;
|
| 538 |
}
|
| 539 |
.profile-badge {
|
| 540 |
display: inline-block;
|
|
|
|
| 599 |
margin-bottom: 15px;
|
| 600 |
}
|
| 601 |
|
| 602 |
+
/* Validation warning box styling */
|
| 603 |
+
.validation-warning-box {
|
| 604 |
+
background-color: #fff3e0;
|
| 605 |
+
border: 1px solid #ff9800;
|
| 606 |
+
border-left: 4px solid #ff9800;
|
| 607 |
border-radius: 8px;
|
| 608 |
+
padding: 20px;
|
| 609 |
+
margin: 20px 0;
|
| 610 |
+
box-shadow: 0 2px 10px rgba(255, 152, 0, 0.1);
|
| 611 |
}
|
| 612 |
+
.validation-warning-box h4 {
|
| 613 |
margin-top: 0;
|
| 614 |
+
color: #e65100;
|
| 615 |
+
margin-bottom: 15px;
|
| 616 |
+
display: flex;
|
| 617 |
+
align-items: center;
|
| 618 |
+
}
|
| 619 |
+
.validation-warning-box .warning-icon {
|
| 620 |
+
margin-right: 10px;
|
| 621 |
+
font-size: 1.2em;
|
| 622 |
+
}
|
| 623 |
+
.validation-warning-box .issue-summary {
|
| 624 |
+
margin-bottom: 15px;
|
| 625 |
+
line-height: 1.6;
|
| 626 |
+
}
|
| 627 |
+
.validation-warning-box .issue-details {
|
| 628 |
+
margin-bottom: 15px;
|
| 629 |
+
}
|
| 630 |
+
.validation-warning-box .issue-list {
|
| 631 |
+
margin: 10px 0;
|
| 632 |
+
padding-left: 20px;
|
| 633 |
+
}
|
| 634 |
+
.validation-warning-box .issue-list li {
|
| 635 |
+
margin-bottom: 8px;
|
| 636 |
+
line-height: 1.5;
|
| 637 |
+
}
|
| 638 |
+
.validation-warning-box .call-to-action {
|
| 639 |
+
margin-top: 15px;
|
| 640 |
+
padding-top: 15px;
|
| 641 |
+
border-top: 1px solid #ffcc80;
|
| 642 |
+
}
|
| 643 |
+
.validation-warning-box .call-to-action p {
|
| 644 |
+
margin-bottom: 10px;
|
| 645 |
+
}
|
| 646 |
+
.issue-tracker-link {
|
| 647 |
+
display: inline-block;
|
| 648 |
+
padding: 8px 16px;
|
| 649 |
+
background-color: #3498db;
|
| 650 |
+
color: white;
|
| 651 |
+
text-decoration: none;
|
| 652 |
+
border-radius: 4px;
|
| 653 |
+
font-weight: 500;
|
| 654 |
+
transition: background-color 0.3s;
|
| 655 |
+
}
|
| 656 |
+
.issue-tracker-link:hover {
|
| 657 |
+
background-color: #2980b9;
|
| 658 |
+
text-decoration: none;
|
| 659 |
+
}
|
| 660 |
+
|
| 661 |
+
/* Category table styling */
|
| 662 |
+
.category-table {
|
| 663 |
+
margin-bottom: 30px;
|
| 664 |
+
}
|
| 665 |
+
.category-table h4 {
|
| 666 |
color: #2c3e50;
|
| 667 |
+
margin-bottom: 10px;
|
| 668 |
+
font-size: 18px;
|
|
|
|
| 669 |
}
|
| 670 |
+
.category-result {
|
| 671 |
+
background-color: #f8f9fa;
|
| 672 |
+
padding: 10px;
|
| 673 |
+
border-radius: 4px;
|
| 674 |
+
margin-top: 10px;
|
| 675 |
+
font-weight: bold;
|
| 676 |
+
}
|
| 677 |
+
.field-type-legend {
|
| 678 |
+
background-color: #e3f2fd;
|
| 679 |
+
border-left: 4px solid #2196f3;
|
| 680 |
+
padding: 15px;
|
| 681 |
+
margin: 20px 0;
|
| 682 |
+
border-radius: 8px;
|
| 683 |
+
font-size: 0.9em;
|
| 684 |
+
}
|
| 685 |
+
.field-type-legend h4 {
|
| 686 |
+
margin-top: 0;
|
| 687 |
+
color: #1565c0;
|
| 688 |
+
margin-bottom: 10px;
|
| 689 |
+
}
|
| 690 |
+
.legend-item {
|
| 691 |
+
display: inline-block;
|
| 692 |
+
margin-right: 20px;
|
| 693 |
+
margin-bottom: 5px;
|
| 694 |
}
|
| 695 |
|
| 696 |
+
/* Support section styling */
|
| 697 |
+
.support-section {
|
| 698 |
+
background-color: #f8f9fa;
|
| 699 |
+
border-left: 4px solid #6c757d;
|
| 700 |
padding: 20px;
|
| 701 |
+
margin: 30px 0;
|
| 702 |
+
border-radius: 8px;
|
| 703 |
+
text-align: center;
|
| 704 |
}
|
| 705 |
+
.support-section h3 {
|
| 706 |
+
margin-top: 0;
|
| 707 |
+
color: #495057;
|
| 708 |
+
margin-bottom: 15px;
|
| 709 |
+
}
|
| 710 |
+
.support-section p {
|
| 711 |
+
margin-bottom: 15px;
|
| 712 |
+
color: #6c757d;
|
| 713 |
+
}
|
| 714 |
+
.github-button {
|
| 715 |
+
display: inline-block;
|
| 716 |
+
padding: 12px 20px;
|
| 717 |
+
background-color: #3498db;
|
| 718 |
+
color: white;
|
| 719 |
+
text-decoration: none;
|
| 720 |
+
border-radius: 6px;
|
| 721 |
+
font-weight: 500;
|
| 722 |
+
transition: background-color 0.3s;
|
| 723 |
+
}
|
| 724 |
+
.github-button:hover {
|
| 725 |
+
background-color: #2980b9;
|
| 726 |
+
text-decoration: none;
|
|
|
|
| 727 |
}
|
| 728 |
</style>
|
| 729 |
</head>
|
| 730 |
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 731 |
<div class="container">
|
| 732 |
+
<!-- Header -->
|
| 733 |
+
<div class="header">
|
| 734 |
+
<div class="header-left">
|
| 735 |
+
<a href="https://aetheris.ai/" target="_blank">
|
| 736 |
+
<img src="https://huggingface.co/spaces/aetheris-ai/aibom-generator/resolve/main/templates/images/AetherisAI-logo.png" alt="Aetheris AI Logo">
|
| 737 |
+
</a>
|
| 738 |
+
<div class="header-content">
|
| 739 |
+
<h1>AI SBOM Generator</h1>
|
| 740 |
+
</div>
|
| 741 |
</div>
|
| 742 |
+
<div class="header-right">
|
| 743 |
+
<!-- <a href="https://aetheris-ai-aibom-generator.hf.space/" class="generate-another-btn">🚀 Generate Another AI SBOM</a> -->
|
| 744 |
+
<a href="/" class="generate-another-btn">🚀 Generate Another AI SBOM</a>
|
| 745 |
+
</div>
|
| 746 |
+
</div>
|
| 747 |
+
|
| 748 |
+
<!-- Success Message
|
| 749 |
+
<div class="success-message">
|
| 750 |
+
<h2>✅ AI SBOM is Generated Successfully for <span class="model-name">{{ model_id }}</span></h2>
|
| 751 |
+
</div> -->
|
| 752 |
|
| 753 |
+
<!-- Key Information -->
|
| 754 |
+
<div class="key-info">
|
| 755 |
+
<h3>📋 AI SBOM Summary for model <span class="model-name">{{ model_id }}</span></h3>
|
| 756 |
+
<div class="aibom-property">
|
| 757 |
+
<span class="property-name">Model:</span>
|
| 758 |
+
<span class="property-value">{{ model_id }}</span>
|
| 759 |
+
</div>
|
| 760 |
+
<div class="aibom-property">
|
| 761 |
+
<span class="property-name">Generated:</span>
|
| 762 |
+
<span class="property-value">{{ aibom.metadata.timestamp }}</span>
|
| 763 |
+
</div>
|
| 764 |
+
<div class="aibom-property">
|
| 765 |
+
<span class="property-name">SBOM Format:</span>
|
| 766 |
+
<span class="property-value">{{ aibom.bomFormat }} {{ aibom.specVersion }}</span>
|
| 767 |
+
</div>
|
| 768 |
+
<div class="aibom-property">
|
| 769 |
+
<span class="property-name">Serial Number:</span>
|
| 770 |
+
<span class="property-value">{{ aibom.serialNumber }}</span>
|
| 771 |
</div>
|
|
|
|
| 772 |
</div>
|
| 773 |
|
| 774 |
+
<!-- Download Section -->
|
| 775 |
+
<div class="download-section">
|
| 776 |
+
<p><strong>Download your AI SBOM:</strong></p>
|
| 777 |
+
<button onclick="downloadJSON()">📥 Download JSON</button>
|
| 778 |
</div>
|
| 779 |
+
|
| 780 |
+
<!-- Completeness Profile -->
|
| 781 |
+
{% if completeness_score.completeness_profile %}
|
| 782 |
+
<div class="completeness-profile">
|
| 783 |
+
<h3>📊 Completeness Assessment</h3>
|
| 784 |
+
<div>
|
| 785 |
+
<span class="profile-badge profile-{{ completeness_score.completeness_profile.name|lower }}">
|
| 786 |
+
{{ completeness_score.completeness_profile.name }}
|
| 787 |
+
</span>
|
| 788 |
+
<span>{{ completeness_score.completeness_profile.description }}</span>
|
| 789 |
+
</div>
|
| 790 |
</div>
|
| 791 |
+
{% endif %}
|
| 792 |
+
|
| 793 |
+
<!-- Tabbed Content -->
|
| 794 |
+
<div class="aibom-viewer">
|
| 795 |
+
<div class="aibom-tabs">
|
| 796 |
+
<div class="aibom-tab active" onclick="switchTab('human-view')">Human-Friendly View</div>
|
| 797 |
+
<div class="aibom-tab" onclick="switchTab('field-checklist')">Field Checklist</div>
|
| 798 |
+
<div class="aibom-tab" onclick="switchTab('score-view')">Score Report</div>
|
| 799 |
+
<div class="aibom-tab" onclick="switchTab('json-view')">JSON View</div>
|
| 800 |
+
</div>
|
| 801 |
|
| 802 |
+
<!-- Human-Friendly View Tab -->
|
| 803 |
+
<div id="human-view" class="tab-content active">
|
| 804 |
+
<div class="aibom-section">
|
| 805 |
+
<h4>🤖 AI Model Information</h4>
|
| 806 |
+
<div class="aibom-property">
|
| 807 |
+
<span class="property-name">Name:</span>
|
| 808 |
+
<span class="property-value">{{ aibom.components[0].name if aibom.components else 'Not specified' }}</span>
|
| 809 |
+
</div>
|
| 810 |
<div class="aibom-property">
|
| 811 |
+
<span class="property-name">Type:</span>
|
| 812 |
+
<span class="property-value">{{ aibom.components[0].type if aibom.components else 'Not specified' }}</span>
|
| 813 |
</div>
|
| 814 |
<div class="aibom-property">
|
| 815 |
+
<span class="property-name">Version:</span>
|
| 816 |
+
<span class="property-value">{{ aibom.components[0].version if aibom.components else 'Not specified' }}</span>
|
| 817 |
</div>
|
| 818 |
<div class="aibom-property">
|
| 819 |
+
<span class="property-name">Description:</span>
|
| 820 |
+
<span class="property-value">{{ aibom.components[0].description if aibom.components and aibom.components[0].description else 'Not specified' }}</span>
|
| 821 |
</div>
|
| 822 |
<div class="aibom-property">
|
| 823 |
+
<span class="property-name">PURL:</span>
|
| 824 |
+
<span class="property-value">{{ aibom.components[0].purl if aibom.components and aibom.components[0].purl else 'Not specified' }}</span>
|
| 825 |
</div>
|
| 826 |
+
{% if aibom.components and aibom.components[0].licenses %}
|
| 827 |
<div class="aibom-property">
|
| 828 |
+
<span class="property-name">Licenses:</span>
|
| 829 |
+
<span class="property-value">
|
| 830 |
+
{% for license in aibom.components[0].licenses %}
|
| 831 |
+
<span class="tag">{{ license.license.id if license.license else 'Unknown' }}</span>
|
| 832 |
+
{% endfor %}
|
| 833 |
+
</span>
|
| 834 |
</div>
|
| 835 |
{% endif %}
|
| 836 |
</div>
|
| 837 |
|
|
|
|
| 838 |
{% if aibom.components and aibom.components[0].modelCard %}
|
| 839 |
<div class="aibom-section">
|
| 840 |
+
<h4>📊 Model Card</h4>
|
| 841 |
+
{% if aibom.components[0].modelCard.modelParameters %}
|
| 842 |
+
<div class="aibom-property">
|
| 843 |
+
<span class="property-name">Architecture:</span>
|
| 844 |
+
<span class="property-value">{{ aibom.components[0].modelCard.modelParameters.modelArchitecture if aibom.components[0].modelCard.modelParameters.modelArchitecture else 'Not specified' }}</span>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 845 |
</div>
|
| 846 |
+
<div class="aibom-property">
|
| 847 |
+
<span class="property-name">Task:</span>
|
| 848 |
+
<span class="property-value">{{ aibom.components[0].modelCard.modelParameters.task if aibom.components[0].modelCard.modelParameters.task else 'Not specified' }}</span>
|
| 849 |
+
</div>
|
| 850 |
+
{% endif %}
|
| 851 |
+
{% if aibom.components[0].modelCard.properties %}
|
| 852 |
+
<div class="aibom-property">
|
| 853 |
+
<span class="property-name">Additional Properties:</span>
|
| 854 |
+
<span class="property-value">
|
| 855 |
+
{% for prop in aibom.components[0].modelCard.properties %}
|
| 856 |
+
<span class="tag">{{ prop.name }}: {{ prop.value }}</span>
|
| 857 |
+
{% endfor %}
|
| 858 |
+
</span>
|
| 859 |
+
</div>
|
| 860 |
+
{% endif %}
|
| 861 |
</div>
|
| 862 |
{% endif %}
|
| 863 |
+
|
| 864 |
+
{% if aibom.externalReferences %}
|
|
|
|
| 865 |
<div class="aibom-section">
|
| 866 |
+
<h4>🔗 External References</h4>
|
| 867 |
+
{% for ref in aibom.externalReferences %}
|
| 868 |
+
<div class="aibom-property">
|
| 869 |
+
<span class="property-name">{{ ref.type|title }}:</span>
|
| 870 |
+
<span class="property-value"><a href="{{ ref.url }}" target="_blank">{{ ref.url }}</a></span>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 871 |
</div>
|
| 872 |
+
{% endfor %}
|
| 873 |
</div>
|
| 874 |
{% endif %}
|
|
|
|
|
|
|
| 875 |
|
| 876 |
+
<div class="aibom-section">
|
| 877 |
+
<h4>🛠️ Generation Metadata</h4>
|
| 878 |
+
<div class="aibom-property">
|
| 879 |
+
<span class="property-name">Generated by:</span>
|
| 880 |
+
<span class="property-value">{{ aibom.metadata.tools.components[0].name if aibom.metadata.tools and aibom.metadata.tools.components else 'Unknown' }}</span>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 881 |
</div>
|
| 882 |
+
<div class="aibom-property">
|
| 883 |
+
<span class="property-name">Timestamp:</span>
|
| 884 |
+
<span class="property-value">{{ aibom.metadata.timestamp }}</span>
|
| 885 |
</div>
|
| 886 |
+
{% if aibom.metadata.component %}
|
| 887 |
+
<div class="aibom-property">
|
| 888 |
+
<span class="property-name">Component Ref:</span>
|
| 889 |
+
<span class="property-value">{{ aibom.metadata.component['bom-ref'] }}</span>
|
| 890 |
</div>
|
| 891 |
+
{% endif %}
|
| 892 |
</div>
|
| 893 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 894 |
|
| 895 |
+
<!-- Field Checklist Tab -->
|
| 896 |
+
<div id="field-checklist" class="tab-content">
|
| 897 |
+
<div class="content-section">
|
| 898 |
+
<h3>Field Checklist & Mapping</h3>
|
| 899 |
+
|
| 900 |
+
<!-- Field Type Legend -->
|
| 901 |
+
<div class="field-type-legend">
|
| 902 |
+
<h4>Legend</h4>
|
| 903 |
+
<div class="legend-item">
|
| 904 |
+
<span class="field-tier tier-critical"></span>
|
| 905 |
+
<span>Critical</span>
|
| 906 |
+
</div>
|
| 907 |
+
<div class="legend-item">
|
| 908 |
+
<span class="field-tier tier-important"></span>
|
| 909 |
+
<span>Important</span>
|
| 910 |
+
</div>
|
| 911 |
+
<div class="legend-item">
|
| 912 |
+
<span class="field-tier tier-supplementary"></span>
|
| 913 |
+
<span>Supplementary</span>
|
| 914 |
+
</div>
|
| 915 |
+
<div class="legend-item">
|
| 916 |
+
<strong>CDX</strong> = CycloneDX Standard
|
| 917 |
+
</div>
|
| 918 |
+
<div class="legend-item">
|
| 919 |
+
<strong>AI</strong> = AI-Specific Extension
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 920 |
</div>
|
| 921 |
</div>
|
| 922 |
+
|
| 923 |
+
<p>This breakdown outlines field categories and statuses in the AI SBOM generated for model <strong>{{ model_id }}</strong>, showing how each field impacts the completeness score.</p>
|
| 924 |
+
|
| 925 |
+
{% if completeness_score.field_checklist %}
|
| 926 |
+
<!-- Required Fields Category -->
|
| 927 |
+
<div class="category-table">
|
| 928 |
+
<h4>Required Fields Category</h4>
|
| 929 |
+
<table>
|
| 930 |
+
<thead>
|
| 931 |
+
<tr>
|
| 932 |
+
<th>Status</th>
|
| 933 |
+
<th>Field Name</th>
|
| 934 |
+
<th>Actual Location</th>
|
| 935 |
+
<th>Tier</th>
|
| 936 |
+
<th>Type</th>
|
| 937 |
+
</tr>
|
| 938 |
+
</thead>
|
| 939 |
+
<tbody>
|
| 940 |
+
{% set required_fields = ['bomFormat', 'specVersion', 'serialNumber', 'version'] %}
|
| 941 |
+
{% for field in required_fields %}
|
| 942 |
+
<tr>
|
| 943 |
+
<td>
|
| 944 |
+
{% if completeness_score.field_checklist.get(field, '').startswith('✔') %}
|
| 945 |
+
<span class="check-mark">✔</span>
|
| 946 |
+
{% else %}
|
| 947 |
+
<span class="x-mark">✘</span>
|
| 948 |
+
{% endif %}
|
| 949 |
+
</td>
|
| 950 |
+
<td>{{ field }}</td>
|
| 951 |
+
<td>
|
| 952 |
+
{% if completeness_score.field_checklist.get(field, '').startswith('✔') %}
|
| 953 |
+
$.{{ field }}
|
| 954 |
+
{% else %}
|
| 955 |
+
Not found
|
| 956 |
+
{% endif %}
|
| 957 |
+
</td>
|
| 958 |
+
<td><span class="field-tier tier-critical"></span> Critical</td>
|
| 959 |
+
<td>CDX</td>
|
| 960 |
+
</tr>
|
| 961 |
+
{% endfor %}
|
| 962 |
+
</tbody>
|
| 963 |
+
</table>
|
| 964 |
+
<div class="category-result">
|
| 965 |
+
Result: {{ completeness_score.category_details.required_fields.present_fields if completeness_score.category_details else 'N/A' }}/{{ completeness_score.category_details.required_fields.total_fields if completeness_score.category_details else 'N/A' }} present
|
| 966 |
+
({{ completeness_score.category_details.required_fields.percentage if completeness_score.category_details else 'N/A' }}%) =
|
| 967 |
+
{{ completeness_score.section_scores.required_fields if completeness_score.section_scores else 'N/A' }}/20 points
|
| 968 |
+
</div>
|
| 969 |
+
</div>
|
| 970 |
|
| 971 |
+
<!-- Metadata Category -->
|
| 972 |
+
<div class="category-table">
|
| 973 |
+
<h4>Metadata Category</h4>
|
| 974 |
+
<table>
|
| 975 |
+
<thead>
|
| 976 |
+
<tr>
|
| 977 |
+
<th>Status</th>
|
| 978 |
+
<th>Field Name</th>
|
| 979 |
+
<th>Actual Location</th>
|
| 980 |
+
<th>Tier</th>
|
| 981 |
+
<th>Type</th>
|
| 982 |
+
</tr>
|
| 983 |
+
</thead>
|
| 984 |
+
<tbody>
|
| 985 |
+
{% set metadata_fields = [
|
| 986 |
+
('primaryPurpose', 'Critical'),
|
| 987 |
+
('suppliedBy', 'Critical'),
|
| 988 |
+
('standardCompliance', 'Supplementary'),
|
| 989 |
+
('domain', 'Supplementary'),
|
| 990 |
+
('autonomyType', 'Supplementary')
|
| 991 |
+
] %}
|
| 992 |
+
{% for field, tier in metadata_fields %}
|
| 993 |
+
<tr>
|
| 994 |
+
<td>
|
| 995 |
+
{% if completeness_score.field_checklist.get(field, '').startswith('✔') %}
|
| 996 |
+
<span class="check-mark">✔</span>
|
| 997 |
+
{% else %}
|
| 998 |
+
<span class="x-mark">✘</span>
|
| 999 |
+
{% endif %}
|
| 1000 |
+
</td>
|
| 1001 |
+
<td>{{ field }}</td>
|
| 1002 |
+
<td>
|
| 1003 |
+
{% if completeness_score.field_checklist.get(field, '').startswith('✔') %}
|
| 1004 |
+
$.metadata.properties[name="{{ field }}"]
|
| 1005 |
+
{% else %}
|
| 1006 |
+
Not found
|
| 1007 |
+
{% endif %}
|
| 1008 |
+
</td>
|
| 1009 |
+
<td><span class="field-tier tier-{{ tier.lower() }}"></span> {{ tier }}</td>
|
| 1010 |
+
<td>AI</td>
|
| 1011 |
+
</tr>
|
| 1012 |
+
{% endfor %}
|
| 1013 |
+
</tbody>
|
| 1014 |
+
</table>
|
| 1015 |
+
<div class="category-result">
|
| 1016 |
+
Result: {{ completeness_score.category_details.metadata.present_fields if completeness_score.category_details else 'N/A' }}/{{ completeness_score.category_details.metadata.total_fields if completeness_score.category_details else 'N/A' }} present
|
| 1017 |
+
({{ completeness_score.category_details.metadata.percentage if completeness_score.category_details else 'N/A' }}%) =
|
| 1018 |
+
{{ completeness_score.section_scores.metadata if completeness_score.section_scores else 'N/A' }}/20 points
|
| 1019 |
</div>
|
| 1020 |
+
</div>
|
| 1021 |
+
|
| 1022 |
+
<!-- Component Basic Category -->
|
| 1023 |
+
<div class="category-table">
|
| 1024 |
+
<h4>Component Basic Category</h4>
|
| 1025 |
+
<table>
|
| 1026 |
+
<thead>
|
| 1027 |
+
<tr>
|
| 1028 |
+
<th>Status</th>
|
| 1029 |
+
<th>Field Name</th>
|
| 1030 |
+
<th>Actual Location</th>
|
| 1031 |
+
<th>Tier</th>
|
| 1032 |
+
<th>Type</th>
|
| 1033 |
+
</tr>
|
| 1034 |
+
</thead>
|
| 1035 |
+
<tbody>
|
| 1036 |
+
{% set component_basic_fields = [
|
| 1037 |
+
('name', 'Critical'),
|
| 1038 |
+
('type', 'Important'),
|
| 1039 |
+
('purl', 'Important'),
|
| 1040 |
+
('description', 'Important'),
|
| 1041 |
+
('licenses', 'Important')
|
| 1042 |
+
] %}
|
| 1043 |
+
{% for field, tier in component_basic_fields %}
|
| 1044 |
+
<tr>
|
| 1045 |
+
<td>
|
| 1046 |
+
{% if completeness_score.field_checklist.get(field, '').startswith('✔') %}
|
| 1047 |
+
<span class="check-mark">✔</span>
|
| 1048 |
+
{% else %}
|
| 1049 |
+
<span class="x-mark">✘</span>
|
| 1050 |
+
{% endif %}
|
| 1051 |
+
</td>
|
| 1052 |
+
<td>{{ field }}</td>
|
| 1053 |
+
<td>
|
| 1054 |
+
{% if completeness_score.field_checklist.get(field, '').startswith('✔') %}
|
| 1055 |
+
$.components[0].{{ field }}
|
| 1056 |
+
{% else %}
|
| 1057 |
+
{% if field == 'description' %}
|
| 1058 |
+
Not found in component level
|
| 1059 |
+
{% else %}
|
| 1060 |
+
Not found
|
| 1061 |
+
{% endif %}
|
| 1062 |
+
{% endif %}
|
| 1063 |
+
</td>
|
| 1064 |
+
<td><span class="field-tier tier-{{ tier.lower() }}"></span> {{ tier }}</td>
|
| 1065 |
+
<td>CDX</td>
|
| 1066 |
+
</tr>
|
| 1067 |
+
{% endfor %}
|
| 1068 |
+
</tbody>
|
| 1069 |
+
</table>
|
| 1070 |
+
<div class="category-result">
|
| 1071 |
+
Result: {{ completeness_score.category_details.component_basic.present_fields if completeness_score.category_details else 'N/A' }}/{{ completeness_score.category_details.component_basic.total_fields if completeness_score.category_details else 'N/A' }} present
|
| 1072 |
+
({{ completeness_score.category_details.component_basic.percentage if completeness_score.category_details else 'N/A' }}%) =
|
| 1073 |
+
{{ completeness_score.section_scores.component_basic if completeness_score.section_scores else 'N/A' }}/20 points
|
| 1074 |
</div>
|
| 1075 |
+
</div>
|
| 1076 |
+
|
| 1077 |
+
<!-- Component Model Card Category -->
|
| 1078 |
+
<div class="category-table">
|
| 1079 |
+
<h4>Component Model Card Category</h4>
|
| 1080 |
+
<table>
|
| 1081 |
+
<thead>
|
| 1082 |
+
<tr>
|
| 1083 |
+
<th>Status</th>
|
| 1084 |
+
<th>Field Name</th>
|
| 1085 |
+
<th>Actual Location</th>
|
| 1086 |
+
<th>Tier</th>
|
| 1087 |
+
<th>Type</th>
|
| 1088 |
+
</tr>
|
| 1089 |
+
</thead>
|
| 1090 |
+
<tbody>
|
| 1091 |
+
{% set model_card_fields = [
|
| 1092 |
+
('energyConsumption', 'Important'),
|
| 1093 |
+
('hyperparameter', 'Important'),
|
| 1094 |
+
('limitation', 'Important'),
|
| 1095 |
+
('safetyRiskAssessment', 'Important'),
|
| 1096 |
+
('typeOfModel', 'Important'),
|
| 1097 |
+
('modelExplainability', 'Supplementary'),
|
| 1098 |
+
('energyQuantity', 'Supplementary'),
|
| 1099 |
+
('energyUnit', 'Supplementary'),
|
| 1100 |
+
('informationAboutTraining', 'Supplementary'),
|
| 1101 |
+
('informationAboutApplication', 'Supplementary'),
|
| 1102 |
+
('metric', 'Supplementary'),
|
| 1103 |
+
('metricDecisionThreshold', 'Supplementary'),
|
| 1104 |
+
('modelDataPreprocessing', 'Supplementary'),
|
| 1105 |
+
('useSensitivePersonalInformation', 'Supplementary')
|
| 1106 |
+
] %}
|
| 1107 |
+
{% for field, tier in model_card_fields %}
|
| 1108 |
+
<tr>
|
| 1109 |
+
<td>
|
| 1110 |
+
{% if completeness_score.field_checklist.get(field, '').startswith('✔') %}
|
| 1111 |
+
<span class="check-mark">✔</span>
|
| 1112 |
+
{% else %}
|
| 1113 |
+
<span class="x-mark">✘</span>
|
| 1114 |
+
{% endif %}
|
| 1115 |
+
</td>
|
| 1116 |
+
<td>{{ field }}</td>
|
| 1117 |
+
<td>
|
| 1118 |
+
{% if completeness_score.field_checklist.get(field, '').startswith('✔') %}
|
| 1119 |
+
{% if field == 'typeOfModel' %}
|
| 1120 |
+
$.metadata.properties[name="{{ field }}"]
|
| 1121 |
+
{% else %}
|
| 1122 |
+
$.components[0].modelCard.{{ field }}
|
| 1123 |
+
{% endif %}
|
| 1124 |
+
{% else %}
|
| 1125 |
+
Not found
|
| 1126 |
+
{% endif %}
|
| 1127 |
+
</td>
|
| 1128 |
+
<td><span class="field-tier tier-{{ tier.lower() }}"></span> {{ tier }}</td>
|
| 1129 |
+
<td>AI</td>
|
| 1130 |
+
</tr>
|
| 1131 |
+
{% endfor %}
|
| 1132 |
+
</tbody>
|
| 1133 |
+
</table>
|
| 1134 |
+
<div class="category-result">
|
| 1135 |
+
Result: {{ completeness_score.category_details.component_model_card.present_fields if completeness_score.category_details else 'N/A' }}/{{ completeness_score.category_details.component_model_card.total_fields if completeness_score.category_details else 'N/A' }} present
|
| 1136 |
+
({{ completeness_score.category_details.component_model_card.percentage if completeness_score.category_details else 'N/A' }}%) =
|
| 1137 |
+
{{ completeness_score.section_scores.component_model_card if completeness_score.section_scores else 'N/A' }}/30 points
|
| 1138 |
</div>
|
| 1139 |
+
</div>
|
| 1140 |
+
|
| 1141 |
+
<!-- External References Category -->
|
| 1142 |
+
<div class="category-table">
|
| 1143 |
+
<h4>External References Category</h4>
|
| 1144 |
+
<table>
|
| 1145 |
<thead>
|
| 1146 |
<tr>
|
| 1147 |
+
<th>Status</th>
|
| 1148 |
+
<th>Field Name</th>
|
| 1149 |
+
<th>Actual Location</th>
|
| 1150 |
+
<th>Tier</th>
|
| 1151 |
+
<th>Type</th>
|
| 1152 |
</tr>
|
| 1153 |
</thead>
|
| 1154 |
<tbody>
|
| 1155 |
+
{% set external_ref_fields = [('downloadLocation', 'Critical')] %}
|
| 1156 |
+
{% for field, tier in external_ref_fields %}
|
| 1157 |
+
<tr>
|
| 1158 |
+
<td>
|
| 1159 |
+
{% if completeness_score.field_checklist.get(field, '').startswith('✔') %}
|
| 1160 |
+
<span class="check-mark">✔</span>
|
| 1161 |
+
{% else %}
|
| 1162 |
+
<span class="x-mark">✘</span>
|
| 1163 |
+
{% endif %}
|
| 1164 |
+
</td>
|
| 1165 |
+
<td>{{ field }}</td>
|
| 1166 |
+
<td>
|
| 1167 |
+
{% if completeness_score.field_checklist.get(field, '').startswith('✔') %}
|
| 1168 |
+
$.externalReferences[type="distribution"]
|
| 1169 |
+
{% else %}
|
| 1170 |
+
Not found
|
| 1171 |
+
{% endif %}
|
| 1172 |
+
</td>
|
| 1173 |
+
<td><span class="field-tier tier-{{ tier.lower() }}"></span> {{ tier }}</td>
|
| 1174 |
+
<td>CDX</td>
|
| 1175 |
+
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1176 |
{% endfor %}
|
| 1177 |
</tbody>
|
| 1178 |
</table>
|
| 1179 |
+
<div class="category-result">
|
| 1180 |
+
Result: {{ completeness_score.category_details.external_references.present_fields if completeness_score.category_details else 'N/A' }}/{{ completeness_score.category_details.external_references.total_fields if completeness_score.category_details else 'N/A' }} present
|
| 1181 |
+
({{ completeness_score.category_details.external_references.percentage if completeness_score.category_details else 'N/A' }}%) =
|
| 1182 |
+
{{ completeness_score.section_scores.external_references if completeness_score.section_scores else 'N/A' }}/10 points
|
| 1183 |
+
</div>
|
| 1184 |
+
</div>
|
| 1185 |
+
|
| 1186 |
+
{% else %}
|
| 1187 |
+
<p>Field checklist data not available.</p>
|
| 1188 |
+
{% endif %}
|
| 1189 |
+
</div>
|
| 1190 |
+
</div>
|
| 1191 |
+
|
| 1192 |
+
<!-- Score Report Tab -->
|
| 1193 |
+
<div id="score-view" class="tab-content">
|
| 1194 |
+
<div class="content-section">
|
| 1195 |
+
<h3>📊 Completeness Score Report</h3>
|
| 1196 |
|
| 1197 |
+
<!-- Total Score Display -->
|
| 1198 |
+
<div class="total-score-container">
|
| 1199 |
+
<div class="total-score">{{ (completeness_score.total_score if completeness_score.total_score != "Undefined" else 0)|round(1) }}/100</div>
|
| 1200 |
+
<div class="total-progress">
|
| 1201 |
+
<div class="progress-container">
|
| 1202 |
+
{% set score_percent = completeness_score.total_score %}
|
| 1203 |
+
{% if score_percent >= 90 %}
|
| 1204 |
+
{% set score_class = 'progress-excellent' %}
|
| 1205 |
+
{% set score_label = 'Excellent' %}
|
| 1206 |
+
{% elif score_percent >= 70 %}
|
| 1207 |
+
{% set score_class = 'progress-good' %}
|
| 1208 |
+
{% set score_label = 'Good' %}
|
| 1209 |
+
{% elif score_percent >= 50 %}
|
| 1210 |
+
{% set score_class = 'progress-fair' %}
|
| 1211 |
+
{% set score_label = 'Fair' %}
|
| 1212 |
+
{% else %}
|
| 1213 |
+
{% set score_class = 'progress-poor' %}
|
| 1214 |
+
{% set score_label = 'Poor' %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1215 |
{% endif %}
|
| 1216 |
+
|
| 1217 |
+
<div class="progress-bar {{ score_class }}" style="width: {{ score_percent }}%">
|
| 1218 |
+
{{ score_percent|int }}% {{ score_label }}
|
| 1219 |
+
</div>
|
| 1220 |
+
</div>
|
| 1221 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1222 |
</div>
|
| 1223 |
+
|
| 1224 |
+
<!-- Generic Scoring Explanation -->
|
| 1225 |
+
<div class="scoring-rubric">
|
| 1226 |
+
<h4>How AI SBOM Completeness is Scored</h4>
|
| 1227 |
+
<p>The completeness score evaluates how well your AI SBOM documents the model across five key categories:</p>
|
|
|
|
|
|
|
| 1228 |
<ul>
|
| 1229 |
+
<li><strong>Required Fields (20 points):</strong> Basic SBOM structure mandated by CycloneDX</li>
|
| 1230 |
+
<li><strong>Metadata (20 points):</strong> Information about the SBOM generation and model purpose</li>
|
| 1231 |
+
<li><strong>Component Basic (20 points):</strong> Essential model identification and licensing</li>
|
| 1232 |
+
<li><strong>Model Card (30 points):</strong> Detailed AI-specific documentation for transparency</li>
|
| 1233 |
+
<li><strong>External References (10 points):</strong> Links to model resources and documentation</li>
|
| 1234 |
</ul>
|
| 1235 |
|
| 1236 |
+
<p><strong>Calculation Method:</strong></p>
|
| 1237 |
+
<p>Each category score = (Present Fields ÷ Total Fields) × Maximum Points</p>
|
| 1238 |
+
<p>Subtotal = Sum of all category scores</p>
|
| 1239 |
+
<p>Final Score = Subtotal × Penalty Factor (if applicable)</p>
|
| 1240 |
+
<h4>Penalty Structure:</h4>
|
| 1241 |
+
<p><strong>Critical Fields Missing:</strong></p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1242 |
<ul>
|
| 1243 |
+
<li>0-1 missing: No penalty</li>
|
| 1244 |
+
<li>2-3 missing: 10% penalty (×0.9)</li>
|
| 1245 |
+
<li>4+ missing: 20% penalty (×0.8)</li>
|
| 1246 |
</ul>
|
| 1247 |
|
| 1248 |
+
<p><strong>Important Fields Missing:</strong></p>
|
| 1249 |
<ul>
|
| 1250 |
+
<li>0-4 missing: No penalty</li>
|
| 1251 |
+
<li>5+ missing: 5% penalty (×0.95)</li>
|
|
|
|
| 1252 |
</ul>
|
| 1253 |
|
| 1254 |
+
<p><strong>Note:</strong> Penalties are cumulative and applied to the subtotal. For example, if you have 3 critical fields missing AND 5 important fields missing, both penalties apply: Subtotal × 0.9 × 0.95 = Final Score.</p>
|
| 1255 |
+
|
| 1256 |
+
</div>
|
| 1257 |
+
|
| 1258 |
+
<!-- Specific Breakdown for This SBOM -->
|
| 1259 |
+
<div class="note-box">
|
| 1260 |
+
<h4>Your AI SBOM Breakdown</h4>
|
| 1261 |
+
<p><strong>Model:</strong> {{ model_id }}</p>
|
| 1262 |
+
|
| 1263 |
+
<table class="score-table">
|
| 1264 |
+
<thead>
|
| 1265 |
+
<tr>
|
| 1266 |
+
<th>Category</th>
|
| 1267 |
+
<th>Fields Present</th>
|
| 1268 |
+
<th>Score</th>
|
| 1269 |
+
<th>Progress</th>
|
| 1270 |
+
</tr>
|
| 1271 |
+
</thead>
|
| 1272 |
+
<tbody>
|
| 1273 |
+
{% if completeness_score.category_details and completeness_score.section_scores %}
|
| 1274 |
+
{% set categories = [
|
| 1275 |
+
('Required Fields', 'required_fields', 20),
|
| 1276 |
+
('Metadata', 'metadata', 20),
|
| 1277 |
+
('Component Basic', 'component_basic', 20),
|
| 1278 |
+
('Model Card', 'component_model_card', 30),
|
| 1279 |
+
('External References', 'external_references', 10)
|
| 1280 |
+
] %}
|
| 1281 |
+
{% for display_name, key, max_score in categories %}
|
| 1282 |
+
<tr>
|
| 1283 |
+
<td>{{ display_name }}</td>
|
| 1284 |
+
<td>{{ completeness_score.category_details[key].present_fields }}/{{ completeness_score.category_details[key].total_fields }}</td>
|
| 1285 |
+
<td>{{ completeness_score.section_scores[key]|round(1) }}/{{ max_score }}</td>
|
| 1286 |
+
<td>
|
| 1287 |
+
<div class="progress-container">
|
| 1288 |
+
{% set percentage = completeness_score.category_details[key].percentage %}
|
| 1289 |
+
{% if percentage >= 80 %}
|
| 1290 |
+
{% set progress_class = "progress-excellent" %}
|
| 1291 |
+
{% elif percentage >= 60 %}
|
| 1292 |
+
{% set progress_class = "progress-good" %}
|
| 1293 |
+
{% elif percentage >= 40 %}
|
| 1294 |
+
{% set progress_class = "progress-fair" %}
|
| 1295 |
+
{% else %}
|
| 1296 |
+
{% set progress_class = "progress-poor" %}
|
| 1297 |
+
{% endif %}
|
| 1298 |
+
<div class="progress-bar {{ progress_class }}" style="width: {{ percentage }}%">{{ percentage|round(0) }}%</div>
|
| 1299 |
+
</div>
|
| 1300 |
+
</td>
|
| 1301 |
+
</tr>
|
| 1302 |
+
{% endfor %}
|
| 1303 |
+
{% else %}
|
| 1304 |
+
<tr><td colspan="4">Breakdown data not available</td></tr>
|
| 1305 |
+
{% endif %}
|
| 1306 |
+
</tbody>
|
| 1307 |
+
</table>
|
| 1308 |
+
</div>
|
| 1309 |
+
|
| 1310 |
+
|
| 1311 |
+
<p><strong>Calculation:</strong></p>
|
| 1312 |
+
<p>Subtotal:
|
| 1313 |
+
{% if completeness_score.section_scores %}
|
| 1314 |
+
{% for category, score in completeness_score.section_scores.items() %}
|
| 1315 |
+
{{ score|round(1) }}{% if not loop.last %} + {% endif %}
|
| 1316 |
+
{% endfor %}
|
| 1317 |
+
= <strong>{{ completeness_score.subtotal_score|round(1) }}/100</strong>
|
| 1318 |
+
{% else %}
|
| 1319 |
+
<strong>{{ completeness_score.subtotal_score|round(1) }}/100</strong>
|
| 1320 |
+
{% endif %}
|
| 1321 |
+
</p>
|
| 1322 |
+
|
| 1323 |
+
{% if completeness_score.penalty_applied %}
|
| 1324 |
+
<p>Penalty Applied: <strong>-{{ completeness_score.penalty_percentage }}%</strong> ({{ completeness_score.penalty_reason }})</p>
|
| 1325 |
+
<p>Final Score: {{ completeness_score.subtotal_score|round(1) }} × {{ completeness_score.penalty_factor }} = <strong>{{ completeness_score.total_score|round(1) }}/100</strong></p>
|
| 1326 |
+
{% else %}
|
| 1327 |
+
<p>No penalties applied</p>
|
| 1328 |
+
<p>Final Score: <strong>{{ completeness_score.total_score|round(1) }}/100</strong></p>
|
| 1329 |
+
{% endif %}
|
| 1330 |
+
</div>
|
| 1331 |
+
|
| 1332 |
+
<!-- Missing Fields Analysis -->
|
| 1333 |
+
{% if completeness_score.missing_counts %}
|
| 1334 |
+
<div class="missing-fields">
|
| 1335 |
+
<h4>Missing Fields Summary</h4>
|
| 1336 |
<ul>
|
| 1337 |
+
<li><strong>Critical:</strong> {{ completeness_score.missing_counts.critical }} missing</li>
|
| 1338 |
+
<li><strong>Important:</strong> {{ completeness_score.missing_counts.important }} missing</li>
|
| 1339 |
+
<li><strong>Supplementary:</strong> {{ completeness_score.missing_counts.supplementary }} missing</li>
|
| 1340 |
</ul>
|
| 1341 |
+
|
| 1342 |
+
{% if completeness_score.missing_counts.important >= 5 %}
|
| 1343 |
+
<p><strong>Impact:</strong> Missing multiple critical and/or important fields will incur penalties according to the Penalty Structure.</p>
|
| 1344 |
{% endif %}
|
| 1345 |
</div>
|
| 1346 |
+
{% endif %}
|
| 1347 |
+
|
| 1348 |
+
<!-- Recommendations -->
|
| 1349 |
+
{% if completeness_score.recommendations %}
|
| 1350 |
+
<div class="recommendations">
|
| 1351 |
+
<h4>General Recommendations to Improve AI SBOM Completeness</h4>
|
| 1352 |
+
<ul>
|
| 1353 |
+
<li><strong>Required Fields:</strong> Ensure the model is published with a clear name, version, and hosting platform information to allow proper SBOM structuring.</li>
|
| 1354 |
+
<li><strong>Metadata:</strong> Include author or organization name, purpose of the model, and relevant timestamps in the model repository or card.</li>
|
| 1355 |
+
<li><strong>Component Basic:</strong> Provide a descriptive model title, a meaningful description, a valid license, and a consistent version reference (e.g., tags or commits).</li>
|
| 1356 |
+
<li><strong>Model Card:</strong> Fill out structured sections for model parameters, evaluation metrics, limitations, and ethical considerations to enable full transparency.</li>
|
| 1357 |
+
<li><strong>External References:</strong> Add links to source code, datasets, documentation, and versioned download locations to support traceability and reproducibility.</li>
|
| 1358 |
+
</ul>
|
| 1359 |
+
</div>
|
| 1360 |
+
{% endif %}
|
| 1361 |
+
</div>
|
| 1362 |
+
</div>
|
| 1363 |
+
|
| 1364 |
+
<!-- JSON View Tab -->
|
| 1365 |
+
<div id="json-view" class="tab-content">
|
| 1366 |
+
<div class="content-section">
|
| 1367 |
+
<h3>📄 Raw JSON View</h3>
|
| 1368 |
+
<p>This is the complete AI SBOM in CycloneDX JSON format:</p>
|
| 1369 |
+
<div class="json-view">
|
| 1370 |
+
<pre>{{ aibom|tojson(indent=2) }}</pre>
|
| 1371 |
+
</div>
|
| 1372 |
</div>
|
| 1373 |
</div>
|
| 1374 |
</div>
|
| 1375 |
|
| 1376 |
+
<!-- Support Section -->
|
| 1377 |
+
<div class="support-section">
|
| 1378 |
+
<h3>🛠️ Need Help or Found an Issue?</h3>
|
| 1379 |
+
<p>If you encountered any problems, found a bug, or have suggestions for improvement, we'd love to hear from you!</p>
|
| 1380 |
+
<a href="https://github.com/aetheris-ai/aibom-generator/issues" target="_blank" class="github-button">
|
| 1381 |
+
Report Issue on GitHub
|
| 1382 |
+
</a>
|
| 1383 |
+
</div>
|
| 1384 |
+
|
| 1385 |
+
<!-- Help us spread the word section -->
|
| 1386 |
<div class="content-section" style="text-align: center;">
|
| 1387 |
<h3>🗣️ Help Us Spread the Word</h3>
|
| 1388 |
<p>If you find this tool useful, share it with your network! <a href="https://sbom.aetheris.ai" target="_blank" rel="noopener noreferrer">https://sbom.aetheris.ai</a></p>
|
|
|
|
| 1395 |
</p>
|
| 1396 |
</div>
|
| 1397 |
|
| 1398 |
+
<!-- Info Section -->
|
| 1399 |
+
<div class="content-section" style="text-align: center;">
|
| 1400 |
<!-- Display the SBOM count -->
|
| 1401 |
<div class="sbom-count">🚀 Generated AI SBOMs using this tool: <strong>{{ sbom_count if sbom_count else 'N/A' }}</strong></div>
|
| 1402 |
</div>
|
| 1403 |
+
|
| 1404 |
<!-- Footer -->
|
| 1405 |
<div class="footer">
|
| 1406 |
<p>© 2025 AI SBOM Generator | Powered by Aetheris AI</p>
|
| 1407 |
</div>
|
| 1408 |
+
</div>
|
| 1409 |
|
| 1410 |
<script>
|
| 1411 |
function switchTab(tabId) {
|
|
|
|
| 1458 |
});
|
| 1459 |
</script>
|
| 1460 |
</body>
|
| 1461 |
+
</html>
|
| 1462 |
+
|