use std::path::PathBuf;
use crate::cli::ReportLevel;
use crate::wcag::Severity;
pub type SignalDetails = Vec<(String, Vec<(String, bool, String)>)>;
pub struct ReportConfig {
pub level: ReportLevel,
pub logo_path: Option<PathBuf>,
pub locale: String,
pub annex: Option<crate::cli::AnnexKind>,
}
impl Default for ReportConfig {
fn default() -> Self {
Self {
level: ReportLevel::Standard,
logo_path: None,
locale: "de".to_string(),
annex: None,
}
}
}
pub use crate::audit::prioritization::{Effort, ExecutionPriority, Priority};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Role {
Development,
Editorial,
DesignUx,
ProjectManagement,
}
impl Role {
pub fn label(&self, en: bool) -> &'static str {
match self {
Role::Development => {
if en {
"Development"
} else {
"Entwicklung"
}
}
Role::Editorial => {
if en {
"Content"
} else {
"Redaktion"
}
}
Role::DesignUx => "Design / UX",
Role::ProjectManagement => {
if en {
"Project management"
} else {
"Projektleitung"
}
}
}
}
}
pub struct FindingSummary {
pub total: usize,
pub critical: usize,
pub high: usize,
pub medium: usize,
pub low: usize,
pub verdict: String,
pub dominant_issue_note: Option<String>,
pub cross_impact_notes: Vec<String>,
pub issue_pattern_label: String,
}
pub struct TaskSummary {
pub blocker_count: usize,
pub high_count: usize,
pub medium_count: usize,
pub low_count: usize,
pub total_count: usize,
pub primary_role: String,
}
pub struct FindingCluster {
pub label: String,
pub dimension: String,
pub finding_count: usize,
pub occurrence_total: usize,
pub severity_label: String,
pub finding_titles: Vec<String>,
}
pub struct DiagnosisBlock {
pub section_title: String,
pub pattern_label: String,
pub pattern_description: String,
pub is_systematic: bool,
pub category_breakdown: Vec<(String, usize, String)>,
pub dominant_issue: Option<String>,
pub verdict_intro: String,
pub clusters: Vec<FindingCluster>,
}
pub struct ReportViewModel {
pub meta: MetaBlock,
pub cover: CoverBlock,
pub summary: SummaryBlock,
pub executive: ExecutiveNarrativeBlock,
pub methodology: MethodologyBlock,
pub modules: ModulesBlock,
pub severity: SeverityBlock,
pub findings: FindingsBlock,
pub diagnosis: DiagnosisBlock,
pub module_details: ModuleDetailsBlock,
pub actions: ActionsBlock,
pub appendix: AppendixBlock,
pub positive_signals: Vec<PositiveSignal>,
pub management_risks: Vec<crate::audit::management_risk::ManagementRiskKind>,
}
pub struct PositiveSignal {
pub title: String,
pub description: String,
pub strong: bool,
}
pub struct MetaBlock {
pub title: String,
pub subtitle: String,
pub date: String,
pub version: String,
pub author: String,
pub report_level: ReportLevel,
pub score_label: String,
}
pub struct CoverBlock {
pub brand: String,
pub title: String,
pub domain: String,
pub subtitle: String,
pub date: String,
pub score: u32,
pub grade: String,
pub certificate: String,
pub maturity_label: String,
pub total_issues: u32,
pub critical_issues: u32,
pub modules: Vec<String>,
pub desktop_score: Option<u32>,
pub mobile_score: Option<u32>,
}
pub struct SummaryBlock {
pub score: u32,
pub overall_score: u32,
pub grade: String,
pub certificate: String,
pub maturity_label: String,
pub problem_type: String,
pub domain: String,
pub date: String,
pub executive_lead: String,
pub dominant_issue_note: Option<String>,
pub audit_quality_note: Option<String>,
pub audit_quality_severe: bool,
pub verdict: String,
pub score_note: Option<String>,
pub ci_verdict: crate::audit::verdict::Verdict,
pub ci_verdict_reasons: Vec<crate::audit::verdict::VerdictReasonKind>,
pub run_is_partial: bool,
pub score_calculation_method: String,
pub score_breakdown: Option<crate::audit::normalized::ScoreBreakdown>,
pub metrics: Vec<MetricItem>,
pub top_actions: Vec<String>,
pub positive_aspects: Vec<String>,
pub overall_impact: Vec<(String, String)>,
pub technical_overview: Vec<String>,
pub benchmark_context: String,
pub business_consequence: String,
pub consequence: String,
pub risk_level: String,
pub risk_summary: String,
}
pub struct ExecutiveNarrativeBlock {
pub cover_eyebrow: String,
pub cover_kicker: String,
pub key_points: Vec<String>,
pub next_steps_callout_body: String,
}
pub struct MetricItem {
pub title: String,
pub value: String,
pub accent_color: Option<String>,
}
pub struct MethodologyBlock {
pub scope: String,
pub method: String,
pub limitations: String,
pub disclaimer: String,
pub audit_facts: Vec<(String, String)>,
pub confidence_summary: Vec<(String, String)>,
pub capabilities: Vec<CapabilitySignal>,
}
pub struct ModulesBlock {
pub dashboard: Vec<ModuleScore>,
pub overall_score: Option<u32>,
pub overall_interpretation: Option<String>,
pub module_scores: Vec<crate::audit::normalized::ModuleScoreEntry>,
pub accessibility_subcategory_scores: Vec<crate::audit::normalized::SubcategoryScoreEntry>,
pub security_category_scores: Vec<crate::audit::normalized::SecurityCategoryScoreEntry>,
}
pub struct ModuleScore {
pub name: String,
pub score: u32,
pub measurement_type: String,
pub interpretation: String,
pub card_context: String,
pub score_context: String,
pub key_lever: String,
pub good_threshold: u32,
pub warn_threshold: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ModuleTaxonomyClass {
Compliance,
Measured,
Composite,
Heuristic,
Optional,
}
impl ModuleTaxonomyClass {
pub fn from_measurement_type(measurement_type: &str, module_name: &str) -> Self {
match measurement_type {
"heuristic" => ModuleTaxonomyClass::Heuristic,
"optional" => ModuleTaxonomyClass::Optional,
"composite" => ModuleTaxonomyClass::Composite,
_ if module_name.eq_ignore_ascii_case("Accessibility") => {
ModuleTaxonomyClass::Compliance
}
_ => ModuleTaxonomyClass::Measured,
}
}
pub fn needs_suffix_qualifier(self) -> bool {
matches!(
self,
ModuleTaxonomyClass::Heuristic | ModuleTaxonomyClass::Optional
)
}
}
#[cfg(test)]
mod taxonomy_tests {
use super::ModuleTaxonomyClass;
#[test]
fn classifies_accessibility_as_compliance() {
assert_eq!(
ModuleTaxonomyClass::from_measurement_type("measured", "Accessibility"),
ModuleTaxonomyClass::Compliance
);
}
#[test]
fn classifies_performance_as_measured() {
assert_eq!(
ModuleTaxonomyClass::from_measurement_type("measured", "Performance"),
ModuleTaxonomyClass::Measured
);
}
#[test]
fn classifies_ux_as_heuristic() {
assert_eq!(
ModuleTaxonomyClass::from_measurement_type("heuristic", "UX"),
ModuleTaxonomyClass::Heuristic
);
}
#[test]
fn classifies_dark_mode_as_optional() {
assert_eq!(
ModuleTaxonomyClass::from_measurement_type("optional", "Dark Mode"),
ModuleTaxonomyClass::Optional
);
}
#[test]
fn classifies_search_experience_as_composite() {
assert_eq!(
ModuleTaxonomyClass::from_measurement_type("composite", "Search Experience"),
ModuleTaxonomyClass::Composite
);
}
#[test]
fn only_heuristic_and_optional_need_a_suffix_qualifier() {
assert!(ModuleTaxonomyClass::Heuristic.needs_suffix_qualifier());
assert!(ModuleTaxonomyClass::Optional.needs_suffix_qualifier());
assert!(!ModuleTaxonomyClass::Compliance.needs_suffix_qualifier());
assert!(!ModuleTaxonomyClass::Measured.needs_suffix_qualifier());
assert!(!ModuleTaxonomyClass::Composite.needs_suffix_qualifier());
}
}
pub struct SeverityBlock {
pub critical: u32,
pub high: u32,
pub medium: u32,
pub low: u32,
pub total: u32,
pub has_issues: bool,
pub component_issues: u32,
pub component_occurrences: u32,
}
pub struct FindingSeverityTier {
pub severity: Severity,
pub label: String,
pub findings: Vec<FindingGroup>,
pub total_occurrences: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum CriticalityTier {
Mandatory,
Optimization,
}
pub fn classify_criticality_tier(category: &str, wcag_level: &str) -> CriticalityTier {
if category == "wcag" && matches!(wcag_level, "A" | "AA") {
CriticalityTier::Mandatory
} else {
CriticalityTier::Optimization
}
}
pub struct FindingCriticalityGroup {
pub tier: CriticalityTier,
pub label: String,
pub eyebrow: String,
pub intro: String,
pub by_severity: Vec<FindingSeverityTier>,
pub total_findings: usize,
pub total_occurrences: usize,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct EvidenceClasses {
pub confirmed_violations: u32,
pub warnings: u32,
pub manual_checks: u32,
}
impl EvidenceClasses {
pub fn is_empty(&self) -> bool {
self.confirmed_violations == 0 && self.warnings == 0 && self.manual_checks == 0
}
}
pub struct FindingsBlock {
pub summary: FindingSummary,
pub evidence: EvidenceClasses,
pub clusters: Vec<FindingCluster>,
pub top_findings: Vec<FindingGroup>,
pub all_findings: Vec<FindingGroup>,
pub by_severity: Vec<FindingSeverityTier>,
pub by_tier: Vec<FindingCriticalityGroup>,
}
pub struct ModuleDetailsBlock {
pub search_experience: Option<SearchExperiencePresentation>,
pub performance: Option<PerformancePresentation>,
pub seo: Option<SeoPresentation>,
pub security: Option<SecurityPresentation>,
pub html_conform: Option<HtmlConformPresentation>,
pub commerce: Option<CommercePresentation>,
pub mobile: Option<MobilePresentation>,
pub ux: Option<UxPresentation>,
pub journey: Option<JourneyPresentation>,
pub dark_mode: Option<DarkModePresentation>,
pub design_quality: Option<DesignQualityPresentation>,
pub ai_transparency: Option<AiTransparencyPresentation>,
pub network_dns: Option<crate::network::dns::NetworkDnsAnalysis>,
pub source_quality: Option<crate::source_quality::SourceQualityAnalysis>,
pub ai_visibility: Option<crate::ai_visibility::AiVisibilityAnalysis>,
pub tech_stack: Option<crate::tech_stack::TechStackAnalysis>,
pub content_visibility: Option<crate::content_visibility::ContentVisibilityAnalysis>,
pub best_practices: Option<crate::best_practices::BestPracticesAnalysis>,
pub patterns: Option<crate::patterns::PatternAnalysis>,
pub has_any: bool,
}
pub struct SearchExperiencePresentation {
pub score: u32,
pub label: String,
pub interpretation: String,
pub components: Vec<SearchExperienceComponent>,
pub warnings: Vec<String>,
}
pub struct SearchExperienceComponent {
pub label: String,
pub score: u32,
pub weight_pct: u32,
pub explanation: String,
}
pub struct DarkModePresentation {
pub supported: bool,
pub score: u32,
pub detection_methods: Vec<String>,
pub color_scheme_css: bool,
pub meta_color_scheme: Option<String>,
pub css_custom_properties: u32,
pub dark_contrast_violations: u32,
pub dark_only_violations: u32,
pub light_only_violations: u32,
pub print_stylesheet_detected: bool,
pub print_interactive_chrome_hidden: bool,
pub print_content_not_clipped: bool,
pub print_clipped_elements: u32,
pub forced_colors_detected: bool,
pub forced_colors_active_matches: bool,
pub forced_color_adjust_count: u32,
pub forced_colors_focus_visible: bool,
pub vision_deficiency_modes: Vec<VisionDeficiencyModePresentation>,
pub issues: Vec<(String, String)>,
}
pub struct VisionDeficiencyModePresentation {
pub mode: String,
pub contrast_violations: u32,
pub new_contrast_violations: u32,
pub use_of_color_violations: u32,
}
pub struct DesignQualityPresentation {
pub warning_count: usize,
pub advisory_count: usize,
pub findings: Vec<DesignQualityFindingPresentation>,
}
pub struct DesignQualityFindingPresentation {
pub rule_id: String,
pub level_label: String,
pub confidence_label: String,
pub selector: String,
pub evidence: String,
pub message: String,
}
pub struct AiTransparencyPresentation {
pub images_checked: usize,
pub findings: Vec<ImageProvenanceFindingPresentation>,
}
pub struct ImageProvenanceFindingPresentation {
pub image_url: String,
pub provenance_label: String,
pub validation_label: String,
pub generator: Option<String>,
pub message: String,
}
pub struct ActionsBlock {
pub roadmap_columns: Vec<RoadmapColumnData>,
pub role_assignments: Vec<RoleAssignment>,
pub intro_text: String,
pub phase_preview: Vec<PhasePreview>,
pub block_title: String,
pub task_summary: TaskSummary,
}
pub struct RoadmapColumnData {
pub title: String,
pub description: String,
pub accent_color: String,
pub items: Vec<RoadmapItemData>,
}
pub struct RoadmapItemData {
pub action: String,
pub role: String,
pub priority: String,
pub execution_priority: String,
pub effort: String,
pub benefit: String,
pub user_effect: String,
pub risk_effect: String,
pub occurrence_count: usize,
pub rule_id: String,
pub leverage: String,
}
pub struct PhasePreview {
pub phase_label: String,
pub accent_color: String,
pub description: String,
pub item_count: usize,
pub top_items: Vec<String>,
}
pub struct AppendixBlock {
pub violations: Vec<AppendixViolation>,
pub score_methodology: String,
pub has_violations: bool,
}
pub struct NarrativeArc {
pub diagnose: String,
pub ursache: String,
pub wirkung: String,
pub umsetzung: String,
}
pub struct FindingGroup {
pub title: String,
pub rule_id: String,
pub wcag_criterion: String,
pub wcag_level: String,
pub help_url: Option<String>,
pub dimension: Option<String>,
pub subcategory: Option<String>,
pub issue_class: Option<String>,
pub severity: Severity,
pub priority: Priority,
pub customer_description: String,
pub user_impact: String,
pub business_impact: String,
pub typical_cause: String,
pub recommendation: String,
pub technical_note: String,
pub confidence: String,
pub false_positive_risk: String,
pub verification: String,
pub complexity: String,
pub complexity_reason: String,
pub complexity_kind: crate::audit::normalized::ComplexityKind,
pub expected_impact: String,
pub expected_impact_kind: crate::audit::normalized::ExpectedImpactKind,
pub bfsg_relevance: String,
pub remediation_priority: String,
pub occurrence_count: usize,
pub affected_urls: Vec<String>,
pub affected_elements: usize,
pub additional_occurrences: usize,
pub pattern_clusters: Vec<FindingPatternCluster>,
pub location_hints: Vec<String>,
pub representative_occurrences: Vec<RepresentativeOccurrence>,
pub responsible_role: Role,
pub effort: Effort,
pub execution_priority: ExecutionPriority,
pub examples: Vec<ExampleBlock>,
pub structural_cause: Option<String>,
pub is_component_issue: bool,
pub criticality_tier: CriticalityTier,
pub narrative: NarrativeArc,
}
pub use crate::audit::occurrence_analysis::{FindingPatternCluster, RepresentativeOccurrence};
pub struct CapabilitySignal {
pub signal: String,
pub source: String,
pub confidence: String,
pub surfaces: Vec<String>,
pub note: String,
}
pub struct ExampleBlock {
pub bad: String,
pub good: String,
pub decorative: Option<String>,
}
pub struct PositiveAspect {
pub area: String,
pub description: String,
}
#[derive(Debug, Clone)]
pub struct PerformanceViewport {
pub score: u32,
pub grade: String,
pub vitals: Vec<(String, String, String)>,
}
pub struct ThrottledPerfEntry {
pub profile_name: String,
pub lcp: String,
pub tbt: String,
pub cls: String,
pub score: u32,
}
pub struct ThirdPartyOriginRow {
pub origin: String,
pub provider: Option<String>,
pub category: Option<String>,
pub request_count: u32,
pub transfer_kb: f64,
pub resource_kinds: String,
}
pub struct ThirdPartyPresentation {
pub origins: Vec<ThirdPartyOriginRow>,
pub total_origins: u32,
pub total_kb: f64,
pub total_requests: u32,
pub is_significant: bool,
pub isolated_impact: Vec<ThirdPartyImpactRow>,
}
pub struct ThirdPartyImpactRow {
pub origin: String,
pub baseline_tbt_ms: f64,
pub without_script_tbt_ms: f64,
pub estimated_impact_ms: f64,
}
pub struct CriticalChainPresentation {
pub max_depth: usize,
pub critical_path_ms: String,
pub critical_path_kb: String,
pub total_requests: usize,
}
pub struct MinificationPresentation {
pub total_count: usize,
pub total_savings_kb: f64,
pub top_assets: Vec<(String, String, String)>, pub legacy_count: usize,
pub legacy_wasted_kb: f64,
pub legacy_assets: Vec<(String, String, String)>, }
pub struct CoveragePresentation {
pub js_used_pct: Option<f64>,
pub js_unused_kb: Option<f64>,
pub css_used_pct: Option<f64>,
pub css_total_rules: Option<u32>,
pub css_used_rules: Option<u32>,
pub duplicate_assets: Vec<DuplicateAssetRow>,
}
pub struct DuplicateAssetRow {
pub kind: String,
pub kb: f64,
pub urls: Vec<String>,
}
pub struct AnimationPresentation {
pub total_count: usize,
pub affected_properties: Vec<String>,
pub findings: Vec<(String, String, String)>, }
pub struct OversizedImageRow {
pub src: String,
pub natural: String,
pub display: String,
}
pub struct ImageEfficiencyPresentation {
pub total_images: usize,
pub modern_format_pct: f64,
pub legacy_count: usize,
pub oversized: Vec<OversizedImageRow>,
}
pub struct PerformancePresentation {
pub score: u32,
pub grade: String,
pub interpretation: String,
pub vitals: Vec<(String, String, String)>,
pub desktop: Option<PerformanceViewport>,
pub mobile: Option<PerformanceViewport>,
pub additional_metrics: Vec<(String, String)>,
pub resource_ratings: Vec<(String, String, String, String)>,
pub recommendations: Vec<String>,
pub render_blocking_metrics: Vec<(String, String)>,
pub render_blocking_suggestions: Vec<String>,
pub has_render_blocking: bool,
pub throttled_profiles: Vec<ThrottledPerfEntry>,
pub cls_attribution: Vec<(String, String, String)>,
pub third_party: Option<ThirdPartyPresentation>,
pub critical_chain: Option<CriticalChainPresentation>,
pub minification: Option<MinificationPresentation>,
pub coverage: Option<CoveragePresentation>,
pub animations: Option<AnimationPresentation>,
pub measurement_warnings: Vec<String>,
}
pub struct SeoPresentation {
pub score: u32,
pub interpretation: String,
pub meta_tags: Vec<(String, String)>,
pub meta_issues: Vec<(String, Severity, String)>,
pub heading_summary: String,
pub social_summary: String,
pub technical_summary: Vec<(String, String)>,
pub tracking_summary: Vec<(String, String)>,
pub tracking_summary_text: String,
pub profile: Option<SeoProfilePresentation>,
pub robots: Option<RobotsPresentation>,
pub page_health: Option<PageHealthPresentation>,
pub serp: Option<SerpPresentation>,
pub image_efficiency: Option<ImageEfficiencyPresentation>,
pub technical_issues: Vec<(String, String, String)>,
}
pub struct SerpPresentation {
pub score: u32,
pub pass_count: u32,
pub warning_count: u32,
pub fail_count: u32,
pub signals: Vec<(String, String, String, String)>,
pub rich_result_types: Vec<String>,
}
pub struct PageHealthPresentation {
pub issues: Vec<(String, String, String)>,
pub url_info: Vec<(String, String)>,
pub html_issues: Vec<(String, u32, String, String)>,
pub html_validator: Option<(String, String)>,
pub www_status: Option<(String, String, bool)>,
pub soft_404: Option<(u16, bool)>,
pub has_any_issue: bool,
}
pub struct RobotsPresentation {
pub error: Option<String>,
pub has_wildcard_disallow_all: bool,
pub blocks_ai_crawlers: bool,
pub blocks_ai_citation: bool,
pub inferred_policy: String,
pub sitemaps: Vec<String>,
pub crawl_delays: Vec<(String, u32)>,
pub bot_rows: Vec<(String, String, usize, usize, bool)>,
pub blocked_ai_bots: Vec<String>,
pub noindex_in_sitemap: Option<bool>,
}
pub struct SeoProfilePresentation {
pub identity_summary: String,
pub site_name: String,
pub content_type: String,
pub language: String,
pub category_hints: Vec<String>,
pub identity_facts: Vec<(String, String)>,
pub page_type: String,
pub page_attributes: Vec<String>,
pub content_depth_score: u32,
pub structural_richness_score: u32,
pub media_text_balance_score: u32,
pub intent_fit_score: u32,
pub page_profile_summary: String,
pub optimization_note: String,
pub page_profile_facts: Vec<(String, String)>,
pub schema_rows: Vec<(String, String, String)>,
pub schema_count: usize,
pub schema_status_summary: String,
pub schema_status_has_errors: bool,
pub schema_status_has_json_ld: bool,
pub schema_status_rows: Vec<(String, String)>,
pub schema_fit_summary: Option<String>,
pub schema_fit_is_success: bool,
pub schema_fit_is_warning: bool,
pub schema_fit_facts: Vec<(String, String)>,
pub schema_rule_rows: Vec<(String, String, String)>,
pub schema_manual_review_rows: Vec<(String, String)>,
pub schema_parity_rows: Vec<(String, String, String)>,
pub signal_rows: Vec<(String, String, String)>,
pub signal_passed: u32,
pub signal_total: u32,
pub signal_details: SignalDetails,
pub maturity_level: String,
pub maturity_description: String,
pub maturity_techniques_used: u32,
pub maturity_techniques_total: u32,
}
pub struct SecurityPresentation {
pub score: u32,
pub grade: String,
pub interpretation: String,
pub band_label: String,
pub headers: Vec<(String, String, String, String)>,
pub ssl_info: Vec<(String, String)>,
pub issues: Vec<(String, Severity, String)>,
pub recommendations: Vec<String>,
pub protection: Vec<(String, String)>,
pub has_waf: bool,
pub has_cdn: bool,
}
pub struct CommercePresentation {
pub page_kind_label: String,
pub product: Option<CommerceProductRow>,
pub trust_pages: Vec<(String, bool)>,
pub findings: Vec<(String, String)>,
}
pub struct CommerceProductRow {
pub score: u32,
pub price: Option<String>,
pub availability: Option<String>,
pub has_shipping_details: bool,
pub has_return_policy: bool,
pub rating: Option<String>,
}
pub struct HtmlConformPresentation {
pub score: u32,
pub checked: bool,
pub interpretation: String,
pub error_count: u32,
pub warning_count: u32,
pub info_count: u32,
pub distinct_defect_count: u32,
pub findings: Vec<(String, String, String, String, u32)>,
pub recommendations: Vec<String>,
}
pub struct MobilePresentation {
pub score: u32,
pub interpretation: String,
pub viewport: Vec<(String, String)>,
pub touch_targets: Vec<(String, String)>,
pub font_analysis: Vec<(String, String)>,
pub content_sizing: Vec<(String, String)>,
pub issues: Vec<(String, Severity, String)>,
}
pub struct UxPresentation {
pub score: u32,
pub a11y_penalty: u32,
pub score_before_a11y_penalty: u32,
pub grade: String,
pub interpretation: String,
pub dimensions: Vec<UxDimensionPresentation>,
pub issues: Vec<UxIssuePresentation>,
}
pub struct UxDimensionPresentation {
pub kind: crate::ux::UxDimensionKind,
pub name: String,
pub score: u32,
pub summary: String,
}
pub struct UxIssuePresentation {
pub kind: crate::ux::UxIssueKind,
pub dimension: String,
pub severity: String,
pub problem: String,
pub impact: String,
pub recommendation: String,
pub values: crate::ux::UxIssueValues,
}
pub struct JourneyPresentation {
pub score: u32,
pub a11y_penalty: u32,
pub score_before_a11y_penalty: u32,
pub grade: String,
pub page_intent: String,
pub interpretation: String,
pub dimensions: Vec<JourneyDimensionPresentation>,
pub friction_points: Vec<FrictionPointPresentation>,
}
pub struct JourneyDimensionPresentation {
pub kind: crate::journey::JourneyDimensionKind,
pub name: String,
pub score: u32,
pub weight_pct: u32,
pub summary: String,
}
pub struct FrictionPointPresentation {
pub kind: crate::journey::FrictionKind,
pub step: String,
pub severity: String,
pub problem: String,
pub impact: String,
pub recommendation: String,
pub values: crate::journey::FrictionValues,
}
#[derive(Clone)]
pub struct ActionItem {
pub action: String,
pub benefit: String,
pub role: Role,
pub priority: Priority,
pub execution_priority: ExecutionPriority,
pub effort: Effort,
pub is_systemic: bool,
pub occurrence_count: usize,
pub rule_id: String,
}
pub struct RoleAssignment {
pub role: Role,
pub responsibilities: Vec<String>,
}
pub struct AppendixViolation {
pub rule: String,
pub rule_name: String,
pub severity: Severity,
pub message: String,
pub fix_suggestion: Option<String>,
pub affected_elements: Vec<AffectedElement>,
}
pub struct AffectedElement {
pub selector: String,
pub node_id: String,
}
pub struct CoverData {
pub title: String,
pub url: String,
pub date: String,
pub version: String,
}
pub struct InteractiveCategoryRow {
pub category: String,
pub affected_urls: usize,
pub max_severity: Severity,
}
pub struct InteractiveJourneySummary {
pub total_pages_tested: usize,
pub pages_with_issues: usize,
pub categories: Vec<InteractiveCategoryRow>,
pub has_critical: bool,
}
pub struct BatchPresentation {
pub cover: CoverData,
pub portfolio_summary: PortfolioSummary,
pub top_issues: Vec<FindingGroup>,
pub issue_frequency: Vec<IssueFrequency>,
pub action_plan: ActionPlan,
pub url_ranking: Vec<UrlSummary>,
pub url_details: Vec<CompactUrlSummary>,
pub url_matrix: Vec<UrlMatrixRow>,
pub appendix: BatchAppendixData,
pub interactive_summary: Option<InteractiveJourneySummary>,
pub template_clusters: Vec<TemplateClusterView>,
}
pub struct TemplateClusterView {
pub rule_id: String,
pub selector: String,
pub confidence: String,
pub affected_pages: usize,
pub headline: String,
pub decision_label: String,
}
pub struct ActionPlan {
pub quick_wins: Vec<ActionItem>,
pub medium_term: Vec<ActionItem>,
pub structural: Vec<ActionItem>,
pub role_assignments: Vec<RoleAssignment>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DuplicateContentGroup {
pub kind: String,
pub value: String,
pub urls: Vec<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MissingTagPrevalence {
pub kind: String,
pub missing_count: usize,
pub total_count: usize,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct CanonicalIssue {
pub kind: String,
pub url: String,
pub detail: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct HreflangIssue {
pub source_url: String,
pub target_url: String,
pub lang: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MinificationInconsistency {
pub url: String,
pub kind: String,
pub minified_on_count: usize,
pub unminified_on_count: usize,
pub total_pages_with_asset: usize,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct RedirectChainIssue {
pub url: String,
pub hop_count: usize,
pub is_loop: bool,
pub chain: Vec<String>,
}
pub struct PortfolioSummary {
pub total_urls: usize,
pub passed: usize,
pub failed: usize,
pub average_score: f64,
pub average_overall_score: u32,
pub total_violations: usize,
pub duration_ms: u64,
pub verdict_text: String,
pub worst_urls: Vec<(String, f32)>,
pub best_urls: Vec<(String, f32)>,
pub severity_distribution: SeverityDistribution,
pub risk_level: String,
pub risk_summary: String,
pub module_averages: Vec<(String, u32)>,
pub active_modules: Vec<String>,
pub domain: String,
pub certificate: String,
pub grade: String,
pub page_type_distribution: Vec<(String, usize, u32)>,
pub distribution_insights: Vec<String>,
pub strongest_content_pages: Vec<(String, String, u32)>,
pub weakest_content_pages: Vec<(String, String, u32)>,
pub top_topics: Vec<(String, usize)>,
pub overlap_pairs: Vec<(String, String, u32)>,
pub near_duplicates: Vec<(String, String, u8)>,
pub crawl_links: Option<CrawlLinkSummary>,
pub budget_summary: Vec<(String, String, usize, String)>,
pub render_blocking_summary: Vec<(String, String)>,
pub schema_distribution: Vec<(String, usize)>,
pub pages_without_schema: usize,
pub duplicate_content: Vec<DuplicateContentGroup>,
pub missing_tag_prevalence: Vec<MissingTagPrevalence>,
pub canonical_issues: Vec<CanonicalIssue>,
pub hreflang_issues: Vec<HreflangIssue>,
pub sitemap_http_issues: Vec<crate::audit::SitemapHttpIssue>,
pub orphan_sitemap_urls: Vec<String>,
pub linked_not_in_sitemap: Vec<String>,
pub robots_conflicts: Vec<crate::audit::RobotsSitemapConflict>,
pub minification_inconsistencies: Vec<MinificationInconsistency>,
pub redirect_chain_issues: Vec<RedirectChainIssue>,
pub crawl_depth_diagnostics: Option<crate::audit::CrawlDepthDiagnostics>,
}
pub struct CrawlLinkSummary {
pub seed_url: String,
pub checked_internal_links: usize,
pub broken_internal_links: Vec<BrokenLinkRow>,
pub checked_external_links: usize,
pub broken_external_links: Vec<BrokenLinkRow>,
pub redirect_chains: Vec<RedirectChainRow>,
}
pub struct BrokenLinkRow {
pub source_url: String,
pub target_url: String,
pub status: String,
pub is_external: bool,
pub severity: String,
pub redirect_hops: u8,
}
pub struct RedirectChainRow {
pub source_url: String,
pub target_url: String,
pub final_url: String,
pub hops: u8,
pub is_external: bool,
}
pub struct SeverityDistribution {
pub critical: usize,
pub high: usize,
pub medium: usize,
pub low: usize,
}
pub struct IssueFrequency {
pub problem: String,
pub wcag: String,
pub occurrences: usize,
pub affected_urls: usize,
pub priority: Priority,
}
pub struct UrlSummary {
pub url: String,
pub score: f32,
pub overall_score: u32,
pub grade: String,
pub critical_violations: usize,
pub total_violations: usize,
pub passed: bool,
pub priority: Priority,
}
pub struct CompactUrlSummary {
pub url: String,
pub score: f32,
pub grade: String,
pub critical_violations: usize,
pub total_violations: usize,
pub page_type: Option<String>,
pub page_attributes: Vec<String>,
pub page_semantic_score: Option<u32>,
pub biggest_lever: String,
pub topic_terms: Vec<String>,
pub top_issues: Vec<String>,
pub module_scores: Vec<(String, u32)>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct UrlMatrixRow {
pub rank: usize,
pub url: String,
pub title: Option<String>,
pub inbound_links: usize,
pub outbound_links: u32,
pub word_count: u32,
}
pub struct BatchAppendixData {
pub per_url: Vec<UrlAppendix>,
}
pub struct UrlAppendix {
pub url: String,
pub violations: Vec<AppendixViolation>,
}