a1c00l commited on
Commit
8adece2
Β·
verified Β·
1 Parent(s): ddddad0

Update templates/result.html

Browse files
Files changed (1) hide show
  1. templates/result.html +377 -316
templates/result.html CHANGED
@@ -380,7 +380,7 @@
380
  {% if enhancement_report and enhancement_report.ai_enhanced %}
381
  <div class="improvement">
382
  <h3>AI Enhancement Results</h3>
383
- <p>This AI SBOM was enhanced using <strong>{{ enhancement_report.ai_model }}</strong></p>
384
  <p>Original Score: {{ enhancement_report.original_score.total_score|default(0)|round(1) }}/100</p>
385
  <p>Enhanced Score: {{ enhancement_report.final_score.total_score|default(0)|round(1) }}/100</p>
386
  <p>Improvement: <span class="improvement-value">+{{ enhancement_report.improvement|default(0)|round(1) }} points</span></p>
@@ -625,179 +625,177 @@
625
  </div>
626
  </div>
627
  {% endif %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
628
  </div>
629
  </div>
630
 
631
  <div id="json-view" class="tab-content">
632
  <div class="json-view">
633
- <pre>{{ aibom|tojson(indent=2) }}</pre>
634
  </div>
635
  </div>
636
 
637
  <div id="field-checklist" class="tab-content">
638
- <h3>AI SBOM Field Completeness</h3>
639
 
 
640
  <div class="tier-legend">
641
  <div class="tier-legend-item">
642
- <div class="field-tier tier-critical"></div>
643
- <span>Critical Fields</span>
644
  </div>
645
  <div class="tier-legend-item">
646
- <div class="field-tier tier-important"></div>
647
- <span>Important Fields</span>
648
  </div>
649
  <div class="tier-legend-item">
650
- <div class="field-tier tier-supplementary"></div>
651
- <span>Supplementary Fields</span>
652
  </div>
653
  </div>
654
 
655
- <table>
656
- <tr>
657
- <th>Field</th>
658
- <th>Status</th>
659
- </tr>
660
- <!-- Basic Information -->
661
- <tr>
662
- <td><div class="field-tier tier-critical"></div> Model Name</td>
663
- <td class="{{ 'present' if aibom.components and aibom.components[0].name else 'missing' }}">
664
- {{ 'Present' if aibom.components and aibom.components[0].name else 'Missing' }}
665
- </td>
666
- </tr>
667
- <tr>
668
- <td><div class="field-tier tier-critical"></div> Model Type</td>
669
- <td class="{{ 'present' if aibom.components and aibom.components[0].type else 'missing' }}">
670
- {{ 'Present' if aibom.components and aibom.components[0].type else 'Missing' }}
671
- </td>
672
- </tr>
673
- <tr>
674
- <td><div class="field-tier tier-critical"></div> Model Version</td>
675
- <td class="{{ 'present' if aibom.components and aibom.components[0].version else 'missing' }}">
676
- {{ 'Present' if aibom.components and aibom.components[0].version else 'Missing' }}
677
- </td>
678
- </tr>
679
- <tr>
680
- <td><div class="field-tier tier-important"></div> Model Description</td>
681
- <td class="{{ 'present' if aibom.components and aibom.components[0].description else 'missing' }}">
682
- {{ 'Present' if aibom.components and aibom.components[0].description else 'Missing' }}
683
- </td>
684
- </tr>
685
-
686
- <!-- Model Card -->
687
- <tr>
688
- <td><div class="field-tier tier-important"></div> Model Parameters</td>
689
- <td class="{{ 'present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.modelParameters else 'missing' }}">
690
- {{ 'Present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.modelParameters else 'Missing' }}
691
- </td>
692
- </tr>
693
- <tr>
694
- <td><div class="field-tier tier-important"></div> Performance Metrics</td>
695
- <td class="{{ 'present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.quantitativeAnalysis and aibom.components[0].modelCard.quantitativeAnalysis.performanceMetrics else 'missing' }}">
696
- {{ 'Present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.quantitativeAnalysis and aibom.components[0].modelCard.quantitativeAnalysis.performanceMetrics else 'Missing' }}
697
- </td>
698
- </tr>
699
- <tr>
700
- <td><div class="field-tier tier-supplementary"></div> Ethical Considerations</td>
701
- <td class="{{ 'present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.considerations and aibom.components[0].modelCard.considerations.ethicalConsiderations else 'missing' }}">
702
- {{ 'Present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.considerations and aibom.components[0].modelCard.considerations.ethicalConsiderations else 'Missing' }}
703
- </td>
704
- </tr>
705
-
706
- <!-- Training Data -->
707
- <tr>
708
- <td><div class="field-tier tier-critical"></div> Training Datasets</td>
709
- <td class="{{ 'present' if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.datasets else 'missing' }}">
710
- {{ 'Present' if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.datasets else 'Missing' }}
711
- </td>
712
- </tr>
713
- <tr>
714
- <td><div class="field-tier tier-important"></div> Data Preprocessing</td>
715
- <td class="{{ 'present' if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.preprocessing else 'missing' }}">
716
- {{ 'Present' if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.preprocessing else 'Missing' }}
717
- </td>
718
- </tr>
719
-
720
- <!-- Training Process -->
721
- <tr>
722
- <td><div class="field-tier tier-important"></div> Training Method</td>
723
- <td class="{{ 'present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.trainingMethod else 'missing' }}">
724
- {{ 'Present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.trainingMethod else 'Missing' }}
725
- </td>
726
- </tr>
727
- <tr>
728
- <td><div class="field-tier tier-important"></div> Hyperparameters</td>
729
- <td class="{{ 'present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.hyperparameters else 'missing' }}">
730
- {{ 'Present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.hyperparameters else 'Missing' }}
731
- </td>
732
- </tr>
733
- <tr>
734
- <td><div class="field-tier tier-supplementary"></div> Compute Infrastructure</td>
735
- <td class="{{ 'present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.computeInfrastructure else 'missing' }}">
736
- {{ 'Present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.computeInfrastructure else 'Missing' }}
737
- </td>
738
- </tr>
739
-
740
- <!-- Evaluation -->
741
- <tr>
742
- <td><div class="field-tier tier-important"></div> Evaluation Metrics</td>
743
- <td class="{{ 'present' if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.metrics else 'missing' }}">
744
- {{ 'Present' if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.metrics else 'Missing' }}
745
- </td>
746
- </tr>
747
- <tr>
748
- <td><div class="field-tier tier-important"></div> Evaluation Datasets</td>
749
- <td class="{{ 'present' if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.datasets else 'missing' }}">
750
- {{ 'Present' if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.datasets else 'Missing' }}
751
- </td>
752
- </tr>
753
-
754
- <!-- Usage -->
755
- <tr>
756
- <td><div class="field-tier tier-important"></div> Intended Use</td>
757
- <td class="{{ 'present' if aibom.components and aibom.components[0].usage and aibom.components[0].usage.intendedUse else 'missing' }}">
758
- {{ 'Present' if aibom.components and aibom.components[0].usage and aibom.components[0].usage.intendedUse else 'Missing' }}
759
- </td>
760
- </tr>
761
- <tr>
762
- <td><div class="field-tier tier-supplementary"></div> Out of Scope Uses</td>
763
- <td class="{{ 'present' if aibom.components and aibom.components[0].usage and aibom.components[0].usage.outOfScopeUses else 'missing' }}">
764
- {{ 'Present' if aibom.components and aibom.components[0].usage and aibom.components[0].usage.outOfScopeUses else 'Missing' }}
765
- </td>
766
- </tr>
767
-
768
- <!-- Licenses -->
769
- <tr>
770
- <td><div class="field-tier tier-critical"></div> Licenses</td>
771
- <td class="{{ 'present' if aibom.components and aibom.components[0].licenses else 'missing' }}">
772
- {{ 'Present' if aibom.components and aibom.components[0].licenses else 'Missing' }}
773
- </td>
774
- </tr>
775
- </table>
776
  </div>
777
 
778
  <div id="score-view" class="tab-content">
779
  <h3>AI SBOM Completeness Score</h3>
780
 
781
- <div class="total-score-container">
782
- <div class="total-score">{{ enhancement_report.final_score.total_score|default(0)|round(1) }}/100</div>
783
- <div class="total-progress">
784
- <div class="progress-container">
785
- {% set score = enhancement_report.final_score.total_score|default(0) %}
786
- <div class="progress-bar
787
- {{- ' progress-excellent' if score >= 80 -}}
788
- {{- ' progress-good' if score >= 60 and score < 80 -}}
789
- {{- ' progress-fair' if score >= 40 and score < 60 -}}
790
- {{- ' progress-poor' if score < 40 -}}"
791
- style="width: {{ score }}%">
792
- {{ score|round(1) }}%
793
- </div>
794
- </div>
795
- </div>
796
  </div>
797
-
798
  <div class="completeness-profile">
799
- {% set score = enhancement_report.final_score.total_score|default(0) %}
800
  <h4>Completeness Profile:
 
801
  {% if score >= 80 %}
802
  <span class="profile-badge profile-advanced">Advanced</span>
803
  {% elif score >= 60 %}
@@ -820,192 +818,255 @@
820
  {% endif %}
821
  </p>
822
  </div>
 
823
 
824
- <table class="score-table">
825
- <tr>
826
- <th>Category</th>
827
- <th>Score</th>
828
- <th>Details</th>
829
- </tr>
830
- <tr>
831
- <td>Basic Information <span class="score-weight">(20%)</span></td>
832
- <td>
833
- {% set basic_score = 0 %}
834
- {% if aibom.components and aibom.components[0].name %}{% set basic_score = basic_score + 5 %}{% endif %}
835
- {% if aibom.components and aibom.components[0].type %}{% set basic_score = basic_score + 5 %}{% endif %}
836
- {% if aibom.components and aibom.components[0].version %}{% set basic_score = basic_score + 5 %}{% endif %}
837
- {% if aibom.components and aibom.components[0].description %}{% set basic_score = basic_score + 5 %}{% endif %}
838
- {{ basic_score }}/20
839
- {% if basic_score >= 15 %}
840
- <span class="score-label label-excellent">Excellent</span>
841
- {% elif basic_score >= 10 %}
842
- <span class="score-label label-good">Good</span>
843
- {% elif basic_score >= 5 %}
844
- <span class="score-label label-fair">Fair</span>
845
- {% else %}
846
- <span class="score-label label-poor">Poor</span>
847
- {% endif %}
848
- </td>
849
- <td>
850
- {% if basic_score < 20 %}
851
- Missing:
852
- {% if not aibom.components or not aibom.components[0].name %}Model Name, {% endif %}
853
- {% if not aibom.components or not aibom.components[0].type %}Model Type, {% endif %}
854
- {% if not aibom.components or not aibom.components[0].version %}Model Version, {% endif %}
855
- {% if not aibom.components or not aibom.components[0].description %}Model Description{% endif %}
856
- {% else %}
857
- All basic information is present.
858
- {% endif %}
859
- </td>
860
- </tr>
861
- <tr>
862
- <td>Training Data <span class="score-weight">(25%)</span></td>
863
- <td>
864
- {% set training_score = 0 %}
865
- {% if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.datasets %}{% set training_score = training_score + 15 %}{% endif %}
866
- {% if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.preprocessing %}{% set training_score = training_score + 10 %}{% endif %}
867
- {{ training_score }}/25
868
- {% if training_score >= 20 %}
869
- <span class="score-label label-excellent">Excellent</span>
870
- {% elif training_score >= 15 %}
871
- <span class="score-label label-good">Good</span>
872
- {% elif training_score >= 10 %}
873
- <span class="score-label label-fair">Fair</span>
874
- {% else %}
875
- <span class="score-label label-poor">Poor</span>
876
- {% endif %}
877
- </td>
878
- <td>
879
- {% if training_score < 25 %}
880
- Missing:
881
- {% if not aibom.components or not aibom.components[0].trainingData or not aibom.components[0].trainingData.datasets %}Training Datasets, {% endif %}
882
- {% if not aibom.components or not aibom.components[0].trainingData or not aibom.components[0].trainingData.preprocessing %}Data Preprocessing{% endif %}
883
- {% else %}
884
- All training data information is present.
885
- {% endif %}
886
- </td>
887
- </tr>
888
- <tr>
889
- <td>Training Process <span class="score-weight">(20%)</span></td>
890
- <td>
891
- {% set process_score = 0 %}
892
- {% if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.trainingMethod %}{% set process_score = process_score + 8 %}{% endif %}
893
- {% if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.hyperparameters %}{% set process_score = process_score + 8 %}{% endif %}
894
- {% if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.computeInfrastructure %}{% set process_score = process_score + 4 %}{% endif %}
895
- {{ process_score }}/20
896
- {% if process_score >= 16 %}
897
- <span class="score-label label-excellent">Excellent</span>
898
- {% elif process_score >= 12 %}
899
- <span class="score-label label-good">Good</span>
900
- {% elif process_score >= 8 %}
901
- <span class="score-label label-fair">Fair</span>
902
- {% else %}
903
- <span class="score-label label-poor">Poor</span>
904
- {% endif %}
905
- </td>
906
- <td>
907
- {% if process_score < 20 %}
908
- Missing:
909
- {% if not aibom.components or not aibom.components[0].trainingProcess or not aibom.components[0].trainingProcess.trainingMethod %}Training Method, {% endif %}
910
- {% if not aibom.components or not aibom.components[0].trainingProcess or not aibom.components[0].trainingProcess.hyperparameters %}Hyperparameters, {% endif %}
911
- {% if not aibom.components or not aibom.components[0].trainingProcess or not aibom.components[0].trainingProcess.computeInfrastructure %}Compute Infrastructure{% endif %}
912
- {% else %}
913
- All training process information is present.
914
- {% endif %}
915
- </td>
916
- </tr>
917
- <tr>
918
- <td>Evaluation <span class="score-weight">(15%)</span></td>
919
- <td>
920
- {% set eval_score = 0 %}
921
- {% if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.metrics %}{% set eval_score = eval_score + 8 %}{% endif %}
922
- {% if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.datasets %}{% set eval_score = eval_score + 7 %}{% endif %}
923
- {{ eval_score }}/15
924
- {% if eval_score >= 12 %}
925
- <span class="score-label label-excellent">Excellent</span>
926
- {% elif eval_score >= 8 %}
927
- <span class="score-label label-good">Good</span>
928
- {% elif eval_score >= 4 %}
929
- <span class="score-label label-fair">Fair</span>
930
- {% else %}
931
- <span class="score-label label-poor">Poor</span>
932
- {% endif %}
933
- </td>
934
- <td>
935
- {% if eval_score < 15 %}
936
- Missing:
937
- {% if not aibom.components or not aibom.components[0].evaluation or not aibom.components[0].evaluation.metrics %}Evaluation Metrics, {% endif %}
938
- {% if not aibom.components or not aibom.components[0].evaluation or not aibom.components[0].evaluation.datasets %}Evaluation Datasets{% endif %}
939
- {% else %}
940
- All evaluation information is present.
941
- {% endif %}
942
- </td>
943
- </tr>
944
- <tr>
945
- <td>Usage & Licensing <span class="score-weight">(20%)</span></td>
946
- <td>
947
- {% set usage_score = 0 %}
948
- {% if aibom.components and aibom.components[0].usage and aibom.components[0].usage.intendedUse %}{% set usage_score = usage_score + 8 %}{% endif %}
949
- {% if aibom.components and aibom.components[0].usage and aibom.components[0].usage.outOfScopeUses %}{% set usage_score = usage_score + 2 %}{% endif %}
950
- {% if aibom.components and aibom.components[0].licenses %}{% set usage_score = usage_score + 10 %}{% endif %}
951
- {{ usage_score }}/20
952
- {% if usage_score >= 16 %}
953
- <span class="score-label label-excellent">Excellent</span>
954
- {% elif usage_score >= 12 %}
955
- <span class="score-label label-good">Good</span>
956
- {% elif usage_score >= 8 %}
957
- <span class="score-label label-fair">Fair</span>
958
  {% else %}
959
- <span class="score-label label-poor">Poor</span>
960
  {% endif %}
961
- </td>
962
- <td>
963
- {% if usage_score < 20 %}
964
- Missing:
965
- {% if not aibom.components or not aibom.components[0].usage or not aibom.components[0].usage.intendedUse %}Intended Use, {% endif %}
966
- {% if not aibom.components or not aibom.components[0].usage or not aibom.components[0].usage.outOfScopeUses %}Out of Scope Uses, {% endif %}
967
- {% if not aibom.components or not aibom.components[0].licenses %}Licenses{% endif %}
968
- {% else %}
969
- All usage and licensing information is present.
 
 
 
 
970
  {% endif %}
971
- </td>
972
- </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973
  </table>
 
974
 
975
- <div class="recommendations">
976
- <h4>Recommendations for Improvement</h4>
 
 
 
977
  <ul>
978
- {% if not aibom.components or not aibom.components[0].name or not aibom.components[0].type or not aibom.components[0].version %}
979
- <li><span class="importance-indicator high-importance">β˜…β˜…β˜…</span> Add basic model information (name, type, version)</li>
980
- {% endif %}
981
-
982
- {% if not aibom.components or not aibom.components[0].trainingData or not aibom.components[0].trainingData.datasets %}
983
- <li><span class="importance-indicator high-importance">β˜…β˜…β˜…</span> Add information about training datasets</li>
984
- {% endif %}
985
-
986
- {% if not aibom.components or not aibom.components[0].licenses %}
987
- <li><span class="importance-indicator high-importance">β˜…β˜…β˜…</span> Add licensing information</li>
988
- {% endif %}
989
-
990
- {% if not aibom.components or not aibom.components[0].trainingProcess or not aibom.components[0].trainingProcess.trainingMethod or not aibom.components[0].trainingProcess.hyperparameters %}
991
- <li><span class="importance-indicator medium-importance">β˜…β˜…β˜†</span> Add training process details (method, hyperparameters)</li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
992
  {% endif %}
 
 
 
 
 
 
 
 
 
 
993
 
994
- {% if not aibom.components or not aibom.components[0].evaluation or not aibom.components[0].evaluation.metrics %}
995
- <li><span class="importance-indicator medium-importance">β˜…β˜…β˜†</span> Add evaluation metrics</li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
996
  {% endif %}
997
 
998
- {% if not aibom.components or not aibom.components[0].usage or not aibom.components[0].usage.intendedUse %}
999
- <li><span class="importance-indicator medium-importance">β˜…β˜…β˜†</span> Add intended use information</li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1000
  {% endif %}
1001
 
1002
- {% if not aibom.components or not aibom.components[0].modelCard or not aibom.components[0].modelCard.considerations or not aibom.components[0].modelCard.considerations.ethicalConsiderations %}
1003
- <li><span class="importance-indicator low-importance">β˜…β˜†β˜†</span> Add ethical considerations</li>
1004
  {% endif %}
1005
- </ul>
1006
  </div>
 
1007
  </div>
1008
 
 
 
1009
  <script>
1010
  function downloadJSON() {
1011
  const a = document.createElement('a');
 
380
  {% if enhancement_report and enhancement_report.ai_enhanced %}
381
  <div class="improvement">
382
  <h3>AI Enhancement Results</h3>
383
+ <p>This AI SBOM was enhanced using <strong>{{ enhancement_report.ai_model|default('AI Model') }}</strong></p>
384
  <p>Original Score: {{ enhancement_report.original_score.total_score|default(0)|round(1) }}/100</p>
385
  <p>Enhanced Score: {{ enhancement_report.final_score.total_score|default(0)|round(1) }}/100</p>
386
  <p>Improvement: <span class="improvement-value">+{{ enhancement_report.improvement|default(0)|round(1) }} points</span></p>
 
625
  </div>
626
  </div>
627
  {% endif %}
628
+
629
+ <!-- Metadata Section -->
630
+ {% if aibom.metadata %}
631
+ <div class="aibom-section">
632
+ <h4 class="collapsible" onclick="toggleCollapsible(this)">Metadata</h4>
633
+ <div class="collapsible-content">
634
+ {% if aibom.metadata.timestamp %}
635
+ <div class="aibom-property">
636
+ <div class="property-name">Timestamp:</div>
637
+ <div class="property-value">{{ aibom.metadata.timestamp }}</div>
638
+ </div>
639
+ {% endif %}
640
+
641
+ {% if aibom.metadata.tools %}
642
+ <div class="aibom-property">
643
+ <div class="property-name">Tools:</div>
644
+ <div class="property-value">
645
+ {% for tool in aibom.metadata.tools %}
646
+ <div>{{ tool.name }} {% if tool.version %}({{ tool.version }}){% endif %}</div>
647
+ {% endfor %}
648
+ </div>
649
+ </div>
650
+ {% endif %}
651
+
652
+ {% if aibom.metadata.authors %}
653
+ <div class="aibom-property">
654
+ <div class="property-name">Authors:</div>
655
+ <div class="property-value">
656
+ {% for author in aibom.metadata.authors %}
657
+ <div>{{ author.name }} {% if author.email %}({{ author.email }}){% endif %}</div>
658
+ {% endfor %}
659
+ </div>
660
+ </div>
661
+ {% endif %}
662
+
663
+ {% if aibom.metadata.properties %}
664
+ <div class="aibom-property">
665
+ <div class="property-name">Properties:</div>
666
+ <div class="property-value">
667
+ {% for prop in aibom.metadata.properties %}
668
+ <div><strong>{{ prop.name }}:</strong> {{ prop.value }}</div>
669
+ {% endfor %}
670
+ </div>
671
+ </div>
672
+ {% endif %}
673
+ </div>
674
+ </div>
675
+ {% endif %}
676
+
677
+ <!-- External References Section -->
678
+ {% if aibom.components and aibom.components[0].externalReferences %}
679
+ <div class="aibom-section">
680
+ <h4 class="collapsible" onclick="toggleCollapsible(this)">External References</h4>
681
+ <div class="collapsible-content">
682
+ {% for ref in aibom.components[0].externalReferences %}
683
+ <div class="aibom-property">
684
+ <div class="property-name">{{ ref.type|title if ref.type else 'Reference' }}:</div>
685
+ <div class="property-value">
686
+ <a href="{{ ref.url }}" target="_blank">{{ ref.url }}</a>
687
+ {% if ref.comment %}<div>{{ ref.comment }}</div>{% endif %}
688
+ </div>
689
+ </div>
690
+ {% endfor %}
691
+ </div>
692
+ </div>
693
+ {% endif %}
694
  </div>
695
  </div>
696
 
697
  <div id="json-view" class="tab-content">
698
  <div class="json-view">
699
+ <pre>{{ aibom | tojson(indent=2) }}</pre>
700
  </div>
701
  </div>
702
 
703
  <div id="field-checklist" class="tab-content">
704
+ <h3>Field Checklist</h3>
705
 
706
+ <!-- Field Tier Legend -->
707
  <div class="tier-legend">
708
  <div class="tier-legend-item">
709
+ <span class="field-tier tier-critical"></span>
710
+ <span>Critical</span>
711
  </div>
712
  <div class="tier-legend-item">
713
+ <span class="field-tier tier-important"></span>
714
+ <span>Important</span>
715
  </div>
716
  <div class="tier-legend-item">
717
+ <span class="field-tier tier-supplementary"></span>
718
+ <span>Supplementary</span>
719
  </div>
720
  </div>
721
 
722
+ {% if completeness_score and completeness_score.field_checklist %}
723
+ <ul>
724
+ {% for field, status in completeness_score.field_checklist.items() %}
725
+ {% if "βœ”" in status %}
726
+ <li class="present">{{ status }} {{ field }}
727
+ {% if completeness_score.field_tiers and field in completeness_score.field_tiers %}
728
+ <span class="field-tier tier-{{ completeness_score.field_tiers[field] }}"></span>
729
+ {% endif %}
730
+ </li>
731
+ {% else %}
732
+ <li class="missing">{{ status }} {{ field }}
733
+ {% if completeness_score.field_tiers and field in completeness_score.field_tiers %}
734
+ <span class="field-tier tier-{{ completeness_score.field_tiers[field] }}"></span>
735
+ {% endif %}
736
+
737
+ {% if field == "component.description" %}
738
+ <span class="importance-indicator high-importance">β˜…β˜…β˜…</span>
739
+ <span class="tooltip">(?)
740
+ <span class="tooltiptext">A detailed description of the model is essential for users to understand its purpose and capabilities. Add a description that is at least 20 characters long.</span>
741
+ </span>
742
+ {% elif field == "component.purl" %}
743
+ <span class="importance-indicator high-importance">β˜…β˜…β˜…</span>
744
+ <span class="tooltip">(?)
745
+ <span class="tooltiptext">Package URL (PURL) is critical for uniquely identifying the model. It should follow the format pkg:huggingface/[owner]/[name]@[version].</span>
746
+ </span>
747
+ {% elif field == "modelCard.modelParameters" %}
748
+ <span class="importance-indicator high-importance">β˜…β˜…β˜…</span>
749
+ <span class="tooltip">(?)
750
+ <span class="tooltiptext">Model parameters provide essential technical details about the model architecture, training, and capabilities.</span>
751
+ </span>
752
+ {% elif field == "modelCard.considerations" %}
753
+ <span class="importance-indicator medium-importance">β˜…β˜…</span>
754
+ <span class="tooltip">(?)
755
+ <span class="tooltiptext">Considerations section should include ethical considerations, limitations, and risks associated with the model.</span>
756
+ </span>
757
+ {% elif field == "externalReferences" %}
758
+ <span class="importance-indicator medium-importance">β˜…β˜…</span>
759
+ <span class="tooltip">(?)
760
+ <span class="tooltiptext">External references provide links to additional resources like model cards, repositories, and datasets.</span>
761
+ </span>
762
+ {% else %}
763
+ <span class="importance-indicator low-importance">β˜…</span>
764
+ <span class="tooltip">(?)
765
+ <span class="tooltiptext">This field contributes to the completeness of your AI SBOM.</span>
766
+ </span>
767
+ {% endif %}
768
+ </li>
769
+ {% endif %}
770
+ {% endfor %}
771
+ </ul>
772
+ {% else %}
773
+ <p>Field checklist information is not available for this AI SBOM.</p>
774
+ {% endif %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
775
  </div>
776
 
777
  <div id="score-view" class="tab-content">
778
  <h3>AI SBOM Completeness Score</h3>
779
 
780
+ <!-- Completeness Profile Section -->
781
+ {% if completeness_score and completeness_score.completeness_profile %}
782
+ <div class="completeness-profile">
783
+ <h4>Completeness Profile:
784
+ <span class="profile-badge profile-{{ completeness_score.completeness_profile.name|default('incomplete')|lower }}">
785
+ {{ completeness_score.completeness_profile.name|default('Incomplete') }}
786
+ </span>
787
+ </h4>
788
+ <p>{{ completeness_score.completeness_profile.description|default('This AI SBOM needs improvement to meet transparency requirements.') }}</p>
789
+
790
+ {% if completeness_score.completeness_profile.next_level %}
791
+ <p><strong>Next level:</strong> {{ completeness_score.completeness_profile.next_level.name }}
792
+ ({{ completeness_score.completeness_profile.next_level.missing_fields_count }} fields to add)</p>
793
+ {% endif %}
 
794
  </div>
795
+ {% elif enhancement_report %}
796
  <div class="completeness-profile">
 
797
  <h4>Completeness Profile:
798
+ {% set score = enhancement_report.final_score.total_score|default(0) %}
799
  {% if score >= 80 %}
800
  <span class="profile-badge profile-advanced">Advanced</span>
801
  {% elif score >= 60 %}
 
818
  {% endif %}
819
  </p>
820
  </div>
821
+ {% endif %}
822
 
823
+ <!-- Total Score with Progress Bar -->
824
+ <div class="total-score-container">
825
+ {% if completeness_score %}
826
+ <div class="total-score">{{ completeness_score.total_score|default(0)|round(1) }}/100</div>
827
+ {% elif enhancement_report %}
828
+ <div class="total-score">{{ enhancement_report.final_score.total_score|default(0)|round(1) }}/100</div>
829
+ {% else %}
830
+ <div class="total-score">0/100</div>
831
+ {% endif %}
832
+
833
+ <div class="total-progress">
834
+ <div class="progress-container">
835
+ {% if completeness_score %}
836
+ {% set score_percent = (completeness_score.total_score|default(0) / 100) * 100 %}
837
+ {% elif enhancement_report %}
838
+ {% set score_percent = (enhancement_report.final_score.total_score|default(0) / 100) * 100 %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
839
  {% else %}
840
+ {% set score_percent = 0 %}
841
  {% endif %}
842
+
843
+ {% set score_class = 'progress-poor' %}
844
+ {% set score_label = 'Poor' %}
845
+
846
+ {% if score_percent >= 90 %}
847
+ {% set score_class = 'progress-excellent' %}
848
+ {% set score_label = 'Excellent' %}
849
+ {% elif score_percent >= 70 %}
850
+ {% set score_class = 'progress-good' %}
851
+ {% set score_label = 'Good' %}
852
+ {% elif score_percent >= 50 %}
853
+ {% set score_class = 'progress-fair' %}
854
+ {% set score_label = 'Fair' %}
855
  {% endif %}
856
+
857
+ <div class="progress-bar {{ score_class }}" style="width: {{ score_percent }}%">
858
+ {{ score_percent|int }}% <span class="score-label label-{{ score_class|replace('progress-', '') }}">{{ score_label }}</span>
859
+ </div>
860
+ </div>
861
+ </div>
862
+
863
+ {% if completeness_score and completeness_score.validation_penalty %}
864
+ <div style="margin-left: 15px; color: #f44336;">{{ completeness_score.validation_penalty }}</div>
865
+ {% endif %}
866
+ </div>
867
+
868
+ <!-- Validation Penalty Explanation -->
869
+ {% if completeness_score and completeness_score.validation_penalty %}
870
+ <div class="validation-penalty-info">
871
+ <h4>About the Validation Penalty</h4>
872
+ <p>Your score includes a penalty because the AIBOM has schema validation issues. These are structural problems that don't comply with the CycloneDX specification requirements.</p>
873
+ <p><strong>How to fix this:</strong> Look at the "Fix Validation Issues" section in the recommendations below. Fixing these issues will remove the penalty and improve your overall score.</p>
874
+ </div>
875
+ {% endif %}
876
+
877
+ <!-- Scoring Rubric -->
878
+ <div class="scoring-rubric">
879
+ <h4>Scoring Rubric</h4>
880
+ <p>The AI SBOM completeness score is calculated based on the following criteria:</p>
881
+ <table>
882
+ <tr>
883
+ <th>Category</th>
884
+ <th>Weight</th>
885
+ <th>Description</th>
886
+ </tr>
887
+ <tr>
888
+ <td>Basic Information</td>
889
+ <td>20%</td>
890
+ <td>Model name, type, version, and description</td>
891
+ </tr>
892
+ <tr>
893
+ <td>Training Data</td>
894
+ <td>25%</td>
895
+ <td>Datasets used for training and preprocessing steps</td>
896
+ </tr>
897
+ <tr>
898
+ <td>Training Process</td>
899
+ <td>20%</td>
900
+ <td>Training method, hyperparameters, and compute infrastructure</td>
901
+ </tr>
902
+ <tr>
903
+ <td>Evaluation</td>
904
+ <td>15%</td>
905
+ <td>Evaluation metrics and datasets</td>
906
+ </tr>
907
+ <tr>
908
+ <td>Usage & Licensing</td>
909
+ <td>20%</td>
910
+ <td>Intended use, out-of-scope uses, and licensing information</td>
911
+ </tr>
912
+ </table>
913
+ <p>Each category is scored based on the presence and quality of relevant fields. The final score is a weighted average of all categories.</p>
914
+ </div>
915
+
916
+ <!-- Section Scores with Progress Bars and Tooltips -->
917
+ {% if completeness_score and completeness_score.section_scores %}
918
+ <table class="score-table">
919
+ <thead>
920
+ <tr>
921
+ <th>Section</th>
922
+ <th>Score</th>
923
+ <th>Weight</th>
924
+ <th>Progress</th>
925
+ </tr>
926
+ </thead>
927
+ <tbody>
928
+ {% set weights = {'required_fields': 20, 'metadata': 20, 'component_basic': 20, 'component_model_card': 30, 'external_references': 10} %}
929
+ {% set tooltips = {
930
+ 'required_fields': 'Basic SBOM fields required by the CycloneDX specification: bomFormat, specVersion, serialNumber, and version.',
931
+ 'metadata': 'Information about the AI SBOM itself: timestamp, tools used to generate it, authors, and component metadata.',
932
+ 'component_basic': 'Basic information about the AI model: type, name, bom-ref, PURL, description, and licenses.',
933
+ 'component_model_card': 'Detailed information about the model: parameters, quantitative analysis, and ethical considerations.',
934
+ 'external_references': 'Links to external resources like model cards, repositories, and datasets.'
935
+ } %}
936
+ {% set display_names = {
937
+ 'required_fields': 'Required Fields',
938
+ 'metadata': 'Metadata',
939
+ 'component_basic': 'Component Basic',
940
+ 'component_model_card': 'Model Card',
941
+ 'external_references': 'External References'
942
+ } %}
943
+ {% for section, score in completeness_score.section_scores.items() %}
944
+ <tr>
945
+ <td>
946
+ {{ display_names[section]|default(section) }}
947
+ <span class="tooltip">(?)
948
+ <span class="tooltiptext">{{ tooltips[section]|default('Section score') }}</span>
949
+ </span>
950
+ </td>
951
+ <td>{{ score|default(0)|round(1) }}/{{ completeness_score.max_scores[section]|default(100) }}</td>
952
+ <td>{{ weights[section]|default(0) }}%</td>
953
+ <td style="width: 50%;">
954
+ <div class="progress-container">
955
+ {% set percent = (score|default(0) / completeness_score.max_scores[section]|default(100)) * 100 %}
956
+ {% set class = 'progress-poor' %}
957
+
958
+ {% if percent >= 90 %}
959
+ {% set class = 'progress-excellent' %}
960
+ {% elif percent >= 70 %}
961
+ {% set class = 'progress-good' %}
962
+ {% elif percent >= 50 %}
963
+ {% set class = 'progress-fair' %}
964
+ {% endif %}
965
+
966
+ <div class="progress-bar {{ class }}" style="width: {{ percent }}%">
967
+ {{ percent|int }}%
968
+ </div>
969
+ </div>
970
+ </td>
971
+ </tr>
972
+ {% endfor %}
973
+ </tbody>
974
  </table>
975
+ {% endif %}
976
 
977
+ <!-- Missing Fields Highlighting -->
978
+ {% if completeness_score and completeness_score.field_checklist %}
979
+ <div class="missing-fields">
980
+ <h4>Critical Missing Fields</h4>
981
+ <p>The following fields are missing or incomplete and have the biggest impact on your score:</p>
982
  <ul>
983
+ {% set missing_critical = [] %}
984
+ {% for field, status in completeness_score.field_checklist.items() %}
985
+ {% if status != "βœ”" %}
986
+ {% if completeness_score.field_tiers and field in completeness_score.field_tiers and completeness_score.field_tiers[field] == 'critical' %}
987
+ {% set _ = missing_critical.append(field) %}
988
+ <li>
989
+ <strong>{{ field }}</strong>
990
+ <span class="field-tier tier-critical"></span>
991
+ {% if field == "component.description" %}
992
+ - Add a detailed description of the model (at least 20 characters)
993
+ {% elif field == "component.purl" %}
994
+ - Add a valid PURL in the format pkg:huggingface/[owner]/[name]@[version]
995
+ {% elif field == "modelCard.modelParameters" %}
996
+ - Add model parameters section with architecture, size, and training details
997
+ {% elif field == "buildTime" %}
998
+ - Add build time information (when the model was built)
999
+ {% elif field == "releaseTime" %}
1000
+ - Add release time information (when the model was released)
1001
+ {% elif field == "primaryPurpose" %}
1002
+ - Add primary purpose information (what the model is designed for)
1003
+ {% else %}
1004
+ - This field is required for comprehensive documentation
1005
+ {% endif %}
1006
+ </li>
1007
+ {% endif %}
1008
+ {% endif %}
1009
+ {% endfor %}
1010
+ {% if missing_critical|length == 0 %}
1011
+ <li>No critical fields are missing. Great job!</li>
1012
  {% endif %}
1013
+ </ul>
1014
+ </div>
1015
+ {% endif %}
1016
+
1017
+ <!-- Actionable Recommendations -->
1018
+ {% if completeness_score %}
1019
+ <div class="recommendations">
1020
+ <h4>Recommendations to Improve Your Score</h4>
1021
+ <ol>
1022
+ {% set has_recommendations = false %}
1023
 
1024
+ {% if completeness_score.section_scores.component_model_card|default(0) < completeness_score.max_scores.component_model_card|default(100) %}
1025
+ {% set has_recommendations = true %}
1026
+ <li>
1027
+ <strong>Enhance Model Card</strong> (+{{ ((completeness_score.max_scores.component_model_card|default(100) - completeness_score.section_scores.component_model_card|default(0)) * 0.3)|round(1) }} points):
1028
+ <ul>
1029
+ {% if "modelCard.modelParameters" not in completeness_score.field_checklist or completeness_score.field_checklist["modelCard.modelParameters"] != "βœ”" %}
1030
+ <li>Add model parameters section with architecture, size, and training details</li>
1031
+ {% endif %}
1032
+ {% if "modelCard.quantitativeAnalysis" not in completeness_score.field_checklist or completeness_score.field_checklist["modelCard.quantitativeAnalysis"] != "βœ”" %}
1033
+ <li>Add quantitative analysis with performance metrics</li>
1034
+ {% endif %}
1035
+ {% if "modelCard.considerations" not in completeness_score.field_checklist or completeness_score.field_checklist["modelCard.considerations"] != "βœ”" %}
1036
+ <li>Add ethical considerations, limitations, and tradeoffs</li>
1037
+ {% endif %}
1038
+ </ul>
1039
+ </li>
1040
  {% endif %}
1041
 
1042
+ {% if completeness_score.section_scores.component_basic|default(0) < completeness_score.max_scores.component_basic|default(100) %}
1043
+ {% set has_recommendations = true %}
1044
+ <li>
1045
+ <strong>Complete Basic Information</strong> (+{{ ((completeness_score.max_scores.component_basic|default(100) - completeness_score.section_scores.component_basic|default(0)) * 0.2)|round(1) }} points):
1046
+ <ul>
1047
+ {% if "component.description" not in completeness_score.field_checklist or completeness_score.field_checklist["component.description"] != "βœ”" %}
1048
+ <li>Add a detailed description of the model (at least 20 characters)</li>
1049
+ {% endif %}
1050
+ {% if "component.purl" not in completeness_score.field_checklist or completeness_score.field_checklist["component.purl"] != "βœ”" %}
1051
+ <li>Add a valid PURL in the format pkg:huggingface/[owner]/[name]@[version]</li>
1052
+ {% endif %}
1053
+ {% if "component.licenses" not in completeness_score.field_checklist or completeness_score.field_checklist["component.licenses"] != "βœ”" %}
1054
+ <li>Add licensing information</li>
1055
+ {% endif %}
1056
+ </ul>
1057
+ </li>
1058
  {% endif %}
1059
 
1060
+ {% if not has_recommendations %}
1061
+ <li>Your AI SBOM is already well-documented. Great job!</li>
1062
  {% endif %}
1063
+ </ol>
1064
  </div>
1065
+ {% endif %}
1066
  </div>
1067
 
1068
+ {{ download_script|safe if download_script else '' }}
1069
+
1070
  <script>
1071
  function downloadJSON() {
1072
  const a = document.createElement('a');