# auditmysite Architecture
This document describes the current implementation. For older browser-design explorations and proposals that are not fully implemented, see [browser-architecture.md](browser-architecture.md).
## Overview
auditmysite is a WCAG 2.1 accessibility checker written in Rust. It uses Chrome DevTools Protocol (CDP) to extract the browser's native Accessibility Tree and analyze it for violations.
```
┌─────────────────────────────────────────────────────────────────┐
│ CLI (main.rs) │
├─────────────────────────────────────────────────────────────────┤
│ Audit Pipeline │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Browser │→ │ AXTree │→ │ WCAG │→ │ Report │ │
│ │ Manager │ │ Extract │ │ Engine │ │ Output │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
## Module Structure
```
src/
├── main.rs # CLI entry point
├── lib.rs # Library exports
├── error.rs # Error types (AuditError)
├── util.rs # Utility functions
│
├── cli/ # Command-line interface
│ ├── args.rs # Clap argument parsing
│ └── config.rs # auditmysite.toml config support
│
├── browser/ # Chrome/Chromium management
│ ├── mod.rs
│ ├── detection.rs # Find Chrome installation
│ ├── installer.rs # Download browser via `browser install`
│ ├── resolver.rs # Browser path resolution
│ ├── manager.rs # Browser lifecycle (launch, navigate, close)
│ └── pool.rs # Page pool for concurrent audits
│
├── accessibility/ # Accessibility Tree handling
│ ├── mod.rs
│ ├── extractor.rs # CDP AXTree extraction
│ ├── tree.rs # AXNode, AXTree structures
│ └── styles.rs # Computed style extraction
│
├── wcag/ # WCAG rule engine
│ ├── mod.rs
│ ├── engine.rs # Rule orchestration
│ ├── types.rs # Violation, Severity, WcagResults
│ └── rules/ # Individual WCAG rules (22 rules)
│ ├── text_alternatives.rs # 1.1.1
│ ├── contrast.rs # 1.4.3
│ ├── keyboard.rs # 2.1.1
│ ├── bypass_blocks.rs # 2.4.1
│ ├── link_purpose.rs # 2.4.4
│ ├── headings.rs # 2.4.6
│ ├── labels.rs # 3.3.2
│ └── ...
│
├── taxonomy/ # Rule taxonomy & classification
│ ├── mod.rs
│ ├── rules.rs # Rule definitions with metadata
│ ├── score.rs # Taxonomy-based score impact helpers
│ └── severity.rs # Severity mapping helpers
│
├── audit/ # Audit orchestration
│ ├── mod.rs
│ ├── pipeline.rs # Single page audit flow
│ ├── batch.rs # Sitemap/batch processing
│ ├── report.rs # AuditReport structure (raw data)
│ ├── normalized.rs # NormalizedReport (enriched, score-corrected)
│ └── scoring.rs # Score calculation
│
├── output/ # Report generation
│ ├── mod.rs
│ ├── cli.rs # Terminal table output
│ ├── json.rs # JSON reports (via NormalizedReport)
│ ├── sr_audit_json.rs # Standalone screen-reader audit JSON sidecar
│ ├── pdf.rs # PDF reports (via renderreport/Typst)
│ ├── report_model.rs # ViewModel structs for PDF
│ ├── report_builder.rs # AuditReport → ViewModel transformation
│ └── snapshot_export.rs # AXTree + journey traces → YAML (--export-snapshot)
│
├── a11y_journey/ # Accessibility Journey Layer (--interactive)
│ ├── mod.rs # Orchestrator: run() single entry point
│ ├── tab_walk.rs # Tab-order recording + focus evaluation
│ ├── skip_link.rs # Skip-link activation journey
│ ├── disclosure_journey.rs # Accordion/disclosure toggle
│ ├── modal_journey.rs # Modal focus-trap verification
│ ├── tabs_journey.rs # TabList navigation
│ ├── menu_journey.rs # DisclosureMenu journey
│ ├── form_error.rs # Form-error announcement (submit + ARIA live)
│ ├── spa_navigation.rs # SPA single-page navigation detection
│ ├── link_inventory.rs # Linktext/heading/landmark inventory (pure AXTree)
│ └── evaluate.rs # Tab-walk finding evaluation
│
├── screen_reader/ # Screen-reader audit primitives
│ ├── mod.rs
│ ├── types.rs # ReadingItem and ignored-node diagnostics
│ ├── announcer.rs # Localized screen-reader announcement strings
│ ├── navigator.rs # Virtual SR navigation lists
│ ├── analyzer.rs # SR-specific issue detection
│ ├── bfsg.rs # WCAG → EN 301 549 → BFSG mapping
│ └── linearizer.rs # AXTree DFS reading-order linearization
│
├── semantic_eval/ # Semantic AI evaluation (--semantic-eval, optional feature)
│ ├── mod.rs # Entry point: run(), SemanticEvalConfig
│ ├── fastembed_eval.rs # Local multilingual embedding (fastembed)
│ ├── mistral.rs # Mistral LLM evaluation (optional API key)
│ └── prompts.rs # Prompt templates
│
├── security/ # Security analysis
│ └── mod.rs # Headers, SSL, SSRF protection
│
├── seo/ # SEO analysis
│ ├── mod.rs
│ ├── meta.rs # Meta tags
│ ├── headings.rs # Heading structure
│ ├── profile.rs # SEO content profile
│ └── ...
│
├── performance/ # Performance metrics
│ ├── mod.rs
│ ├── vitals.rs # Core Web Vitals
│ └── ...
│
└── mobile/ # Mobile friendliness
└── mod.rs
```
## Data Flow
### Single URL Audit
```
1. CLI parses arguments
│
2. validate_url() checks for SSRF
│
3. BrowserManager launches Chrome
│
4. Navigate to URL, wait for load
│
5. Extract AXTree via CDP
│ └── GetFullAXTreeParams
│
6. Run WCAG rules against AXTree
│ ├── Level A rules
│ ├── Level AA rules (if requested)
│ └── Level AAA rules (if requested)
│
7. Calculate raw score → AuditReport
│
8. Normalize: AuditReport → NormalizedReport
│ ├── Apply score corrections (e.g. 3.1.1 lang suppression)
│ ├── Enrich findings with taxonomy fields
│ └── Compute grade + certificate from corrected score
│
9. Generate report (JSON/PDF/Table)
│ └── All formats use NormalizedReport as single source of truth
│
10. Close browser
```
### Batch Audit (Sitemap)
```
1. Fetch and parse sitemap.xml
│
2. Create BrowserPool with N pages
│
3. For each URL (concurrent):
│ ├── Acquire page from pool
│ ├── Run single audit
│ ├── Return page to pool
│ └── Report progress
│
4. Aggregate results
│
5. Generate batch report
```
## Key Components
### NormalizedReport
Central data layer between raw `AuditReport` and output formats:
- Applies score corrections (e.g. 3.1.1 language suppression)
- Enriches violations with taxonomy metadata (dimension, subcategory, issue_class, etc.)
- Computes grade and certificate from corrected score
- Single source of truth for JSON, PDF, and CLI output — ensures consistent scores
### BrowserManager
Handles Chrome lifecycle:
- Auto-detects Chrome/Chromium installation
- Explicit download via `auditmysite browser install`
- Configures headless mode with security flags
- Manages page navigation with timeouts
### BrowserPool
For concurrent audits:
- Pre-creates N pages
- Reuses pages between audits (reset to about:blank)
- Handles page failures gracefully
- Timeout protection on page reset
### AXTree Extractor
Uses CDP `Accessibility.getFullAXTree`:
- Converts CDP response to internal AXNode structure
- Preserves parent/child relationships
- Extracts properties (role, name, focusable, etc.)
### WCAG Engine
Orchestrates rule checking:
- Filters rules by WCAG level (A, AA, AAA)
- Runs each rule against relevant nodes
- Collects violations with severity
- Counts passes for scoring
### Rule Structure
Each rule implements checking logic:
```rust
pub fn check(tree: &AXTree, _styles: &[NodeStyle], level: WcagLevel) -> Vec<Violation> {
let mut violations = Vec::new();
for node in tree.iter() {
if should_check(node) && has_violation(node) {
violations.push(Violation::new(
"1.1.1",
"Non-text Content",
level,
Severity::High,
"Image missing alt text",
&node.node_id,
));
}
}
violations
}
```
### Taxonomy
Maps WCAG rule IDs to rich metadata:
- **Dimension**: Barrierefreiheit, Usability, etc.
- **Subcategory**: Inhalte & Alternativen, Navigation, etc.
- **IssueClass**: Fehlend, Falsch, Unvollständig
- **ScoreImpact**: Base penalty, max penalty, scaling curve
- **ReportVisibility**: Which report levels (Executive/Standard/Technical) include each finding
## Security Considerations
### SSRF Protection
`validate_url()` blocks:
- Private IPs (10.x, 172.16-31.x, 192.168.x)
- Localhost (127.x, ::1)
- Link-local (169.254.x)
- Non-HTTP schemes
### Path Traversal
`read_url_file()` uses `canonicalize()` to prevent `../` attacks.
### Chromium Downloads
- Pinned version constant
- Trusted CDN (storage.googleapis.com)
- HTTPS only
## Testing Strategy
```
tests/
├── url_validation_tests.rs # SSRF protection
├── output_format_tests.rs # Report generation
└── error_handling_tests.rs # Error paths
src/*/tests (inline) # Unit tests per module
```
Run all tests:
```bash
cargo test
```
## Performance
- Single audit: ~2-5 seconds (depends on page complexity)
- Batch audit: Linear scaling with concurrency
- Memory: ~100MB per Chrome page
## Dependencies
Key crates:
- `chromiumoxide` - CDP client
- `tokio` - Async runtime
- `clap` - CLI parsing
- `serde` - Serialization
- `tracing` - Logging
- `renderreport` - PDF generation (Typst-based)