Website security-configuration auditor implementing foundation-web-analysis::Analyzer -- TLS/certificate validity, HTTP security headers, DNS/SPF/DMARC/CAA record correctness, and exposed-path/WordPress/cookie/open-port checks against a standard
| Tier | infrastructure |
| Role | unclassified (baselined) |
| Path | crates/infrastructure/web-security-audit |
| Edition | 2021 |
| Targets | infrastructure_web_security_audit |
| Public items | 62 across 3 modules |
| Tests | 142 |
What it is for
# infrastructure-web-security-audit
Website security-configuration auditor implementing foundation_web_analysis::Analyzer. Audits a website's TLS/certificate validity and HTTP security headers (tls_headers), DNS/SPF/DMARC/CAA record correctness (dns_email), and exposed sensitive paths/WordPress fingerprinting/cookie flags/open dangerous ports (exposed_paths) against a fixed standard, then derives a 0-100 score per concern plus an overall weighted score.
Lifted from plumber/src/analyzers/security_scanner.rs (sprint 3.46, wave 3 -- see CHANGELOG.md for full provenance). One crate, three internal check modules -- decided by Gate 1.5 Round 1's unanimous 4-seat consensus (docs/userstories/sprint-3.46-plumber-harvest.md): lift the source's coupled sequential analyze() path as-is, with module boundaries drawn now so a later crate-level split is mechanical, rather than inventing crate architecture mid-harvest.
A fourth module the sprint doc proposed, scheduling_alerting (scheduled-scan orchestration, alerting, scan-diff comparison), is a non-goal of this crate -- see the CHANGELOG.md "OQ6" entry for the traced evidence: it has zero callers anywhere in the source, including the source's own scan()/Analyzer::analyze() path, so the three check modules below are everything this crate needs to work identically to the source.
Naming
This crate's own name and this file's is deliberate: it audits configuration against a standard (TLS validity, header presence, DNS record correctness, cookie flags) -- infrastructure-security-scan/ tools-net-probe already own "scan"/"probe" for genuine network-liveness mechanisms, so this crate never uses "scan" in its public API even though its source used it throughout (SecurityScanner -> SecurityAuditor, SecurityScanResult -> SecurityAuditResult, scan() -> SecurityAuditor::audit).
Capabilities
crate root
# infrastructure-web-security-audit
| Item |
|---|
pub const DEFAULT_MAX_HEADERS_PROBE_BYTES: usize |
IssueCategory
# infrastructure-web-security-audit
| Item |
|---|
pub enum IssueCategory |
SecurityAuditResult
# infrastructure-web-security-audit
| Item |
|---|
pub struct SecurityAuditResult |
SecurityAuditResult :: fn new(organization_id : Uuid, domain : & str, url : & str) -> Self |
SecurityAuditResult :: fn add_issue(& mut self, issue : SecurityIssue) |
SecurityAuditResult :: fn calculate_scores(& mut self) |
SecurityAuditor
# infrastructure-web-security-audit
| Item |
|---|
pub struct SecurityAuditor |
SecurityAuditor :: fn new() -> std::result::Result <Self, infrastructure_fetcher::SafeHttpError> |
SecurityAuditor :: fn with_tls_timeout(mut self, timeout : Duration) -> Self |
SecurityAuditor :: async fn audit(& self, url : & str) -> std::result::Result <SecurityAuditResult, String> |
SecurityAuditor :: fn default() -> Self |
SecurityAuditor :: fn name(& self) -> & 'static str |
SecurityAuditor :: async fn analyze(& self, organization_id : Uuid, website_url : & str) -> Result <AnalysisResult> |
SecurityAuditor :: fn cache_ttl_days(& self) -> u32 |
SecurityIssue
# infrastructure-web-security-audit
| Item |
|---|
pub struct SecurityIssue |
Severity
# infrastructure-web-security-audit
| Item |
|---|
pub enum Severity |
CaaRecord
DNS-security (nameservers, DNSSEC, CAA, IPv6) and email-authentication
| Item |
|---|
pub struct CaaRecord |
DmarcPolicy
DNS-security (nameservers, DNSSEC, CAA, IPv6) and email-authentication
| Item |
|---|
pub enum DmarcPolicy |
DnsCheckResult
DNS-security (nameservers, DNSSEC, CAA, IPv6) and email-authentication
| Item |
|---|
pub struct DnsCheckResult |
fn calculate_dns_score(dns : & DnsCheckResult) -> u8 |
async fn check_dns(resolver : & TokioResolver, domain : & str) -> DnsCheckResult |
fn generate_dns_issues(dns : & DnsCheckResult) -> Vec <SecurityIssue> |
EmailCheckResult
DNS-security (nameservers, DNSSEC, CAA, IPv6) and email-authentication
| Item |
|---|
pub struct EmailCheckResult |
fn calculate_email_score(email : & EmailCheckResult) -> u8 |
async fn check_email(resolver : & TokioResolver, domain : & str) -> EmailCheckResult |
fn generate_email_issues(email : & EmailCheckResult) -> Vec <SecurityIssue> |
SpfPolicy
DNS-security (nameservers, DNSSEC, CAA, IPv6) and email-authentication
| Item |
|---|
pub enum SpfPolicy |
exposed_paths (other)
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub const DANGEROUS_PORTS: & (u16, & str, Severity) |
pub const DEFAULT_PROBE_TIMEOUT: Duration |
pub const DEFAULT_PORT_TIMEOUT: Duration |
pub const DEFAULT_MAX_README_BYTES: usize |
fn extract_wp_version_from_readme(html : & str) -> Option <String> |
CookieCheckResult
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub struct CookieCheckResult |
fn calculate_cookies_score(cookies : & CookieCheckResult) -> u8 |
async fn check_cookies(http : & SafeHttpClient, url : & str) -> CookieCheckResult |
fn generate_cookie_issues(cookies : & CookieCheckResult) -> Vec <SecurityIssue> |
CookieInfo
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub struct CookieInfo |
fn parse_cookie(cookie_str : & str) -> Option <CookieInfo> |
ExposedPath
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub struct ExposedPath |
ExposedPathCategory
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub enum ExposedPathCategory |
pub const SENSITIVE_PATHS: & (& str, ExposedPathCategory, Severity) |
ExposedPathsCheckResult
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub struct ExposedPathsCheckResult |
async fn check_exposed_paths(http : & SafeHttpClient, base_url : & str) -> ExposedPathsCheckResult |
fn generate_exposed_paths_issues(exposed : & ExposedPathsCheckResult) -> Vec <SecurityIssue> |
PortCheckResult
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub struct PortCheckResult |
async fn check_ports(resolver : & TokioResolver, domain : & str) -> PortCheckResult |
fn generate_port_issues(ports : & PortCheckResult) -> Vec <SecurityIssue> |
PortInfo
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub struct PortInfo |
SameSitePolicy
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub enum SameSitePolicy |
TechnologyCheckResult
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub struct TechnologyCheckResult |
WordPressCheckResult
Exposed sensitive-path/WordPress-fingerprint, cookie-flag, and
| Item |
|---|
pub struct WordPressCheckResult |
async fn check_wordpress(http : & SafeHttpClient, base_url : & str,) -> Option <WordPressCheckResult> |
fn generate_wordpress_issues(wordpress : Option <& WordPressCheckResult>) -> Vec <SecurityIssue> |
tls_headers (other)
TLS/certificate validity and HTTP security-header checks.
| Item |
|---|
pub const DEFAULT_TLS_TIMEOUT: Duration |
fn generate_issues(ssl : & SslCheckResult, headers : & HeadersCheckResult) -> Vec <SecurityIssue> |
HeadersCheckResult
TLS/certificate validity and HTTP security-header checks.
| Item |
|---|
pub struct HeadersCheckResult |
fn calculate_headers_score(h : & HeadersCheckResult) -> u8 |
fn parse_security_headers(headers : & HeaderMap) -> HeadersCheckResult |
async fn check_headers(http : & SafeHttpClient, url : & Url, max_body_bytes : usize,) -> Result <HeadersCheckResult> |
SslCheckResult
TLS/certificate validity and HTTP security-header checks.
| Item |
|---|
pub struct SslCheckResult |
fn calculate_ssl_score(ssl : & SslCheckResult) -> u8 |
async fn check_ssl(resolver : & TokioResolver, domain : & str, timeout : Duration,) -> SslCheckResult |
How to use it
No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.
Module structure
infrastructure_web_security_audit
dns_emailexposed_pathstls_headers
flowchart TD n_infrastructure_web_security_audit["infrastructure_web_security_audit"] n_infrastructure_web_security_audit --> n_dns_email["dns_email"] n_infrastructure_web_security_audit --> n_exposed_paths["exposed_paths"] n_infrastructure_web_security_audit --> n_tls_headers["tls_headers"]
Public surface
`crate root`
| Item | What it is |
|---|---|
pub struct SecurityIssue | Security issue found during an audit. |
pub enum IssueCategory | Category shared across all three check modules -- not owned by any one of them, so it lives at the crate root. |
pub enum Severity | — |
pub struct SecurityAuditResult | Security audit result: per-concern check results, 0-100 scores, and the flattened issue list with severity counts |
SecurityAuditResult :: fn new(organization_id : Uuid, domain : & str, url : & str) -> Self | — |
SecurityAuditResult :: fn add_issue(& mut self, issue : SecurityIssue) | — |
SecurityAuditResult :: fn calculate_scores(& mut self) | Recompute every per-concern score plus Self::overall_score from the current check results and issue counts |
pub const DEFAULT_MAX_HEADERS_PROBE_BYTES: usize | Default per-fetch byte cap for the headers-check probe body drain (Gate 1.5.6 input limit) -- only headers are consumed, so this bounds a misbehaving/oversized response rather than sizing real content. |
pub struct SecurityAuditor | Security-configuration auditor: TLS/certificate validity, HTTP security headers, DNS/SPF/DMARC/CAA correctness, and exposed-path/WordPress/ cookie/open-port checks against a fixed standard |
SecurityAuditor :: fn new() -> std::result::Result <Self, infrastructure_fetcher::SafeHttpError> | Build an auditor with the default TLS timeout (tls_headers::DEFAULT_TLS_TIMEOUT) and headers-probe byte cap (DEFAULT_MAX_HEADERS_PROBE_BYTES). |
SecurityAuditor :: fn with_tls_timeout(mut self, timeout : Duration) -> Self | Override the TCP-connect + TLS-handshake timeout used by tls_headers::check_ssl. |
SecurityAuditor :: async fn audit(& self, url : & str) -> std::result::Result <SecurityAuditResult, String> | Run every check across the three modules against url, generate issues from each, and compute scores |
SecurityAuditor :: fn default() -> Self | # Panics Panics if the underlying SafeHttpClient cannot be built (TLS backend init failure) -- matches infrastructure-web-domain-intel's expect-on-construction Default impl. |
SecurityAuditor :: fn name(& self) -> & 'static str | — |
SecurityAuditor :: async fn analyze(& self, organization_id : Uuid, website_url : & str) -> Result <AnalysisResult> | — |
SecurityAuditor :: fn cache_ttl_days(& self) -> u32 | — |
`dns_email`
| Item | What it is |
|---|---|
pub struct DnsCheckResult | DNS security check results. |
pub struct CaaRecord | CAA (Certificate Authority Authorization) record. |
pub struct EmailCheckResult | Email security check results (SPF, DKIM, DMARC). |
pub enum SpfPolicy | — |
pub enum DmarcPolicy | — |
fn calculate_dns_score(dns : & DnsCheckResult) -> u8 | Compute the 0-100 DNS-security score from a DnsCheckResult. |
fn calculate_email_score(email : & EmailCheckResult) -> u8 | Compute the 0-100 email-authentication score from an EmailCheckResult. |
async fn check_dns(resolver : & TokioResolver, domain : & str) -> DnsCheckResult | — |
async fn check_email(resolver : & TokioResolver, domain : & str) -> EmailCheckResult | Check MX presence and SPF/DMARC/DKIM records for domain's mail setup. |
fn generate_dns_issues(dns : & DnsCheckResult) -> Vec <SecurityIssue> | Generate SecurityIssues from the DNS check result. |
fn generate_email_issues(email : & EmailCheckResult) -> Vec <SecurityIssue> | Generate SecurityIssues from the email check result. |
`exposed_paths`
| Item | What it is |
|---|---|
pub struct ExposedPathsCheckResult | Exposed paths/files check results. |
pub struct ExposedPath | An exposed sensitive path or file. |
pub enum ExposedPathCategory | — |
pub struct TechnologyCheckResult | Technology/CMS-specific check results. |
pub struct WordPressCheckResult | WordPress-specific security checks. |
pub struct CookieCheckResult | Cookie security check results. |
pub struct CookieInfo | Information about a cookie's security properties. |
pub enum SameSitePolicy | — |
pub struct PortCheckResult | Port scan check results. |
pub struct PortInfo | Information about an open port. |
pub const SENSITIVE_PATHS: & (& str, ExposedPathCategory, Severity) | Paths to check for exposed sensitive files. |
pub const DANGEROUS_PORTS: & (u16, & str, Severity) | Common dangerous ports to check. |
pub const DEFAULT_PROBE_TIMEOUT: Duration | Per-request timeout used by the exposed-path/WordPress HEAD/GET probes (matches the source's own 5s per-request timeout). |
pub const DEFAULT_PORT_TIMEOUT: Duration | Per-port TCP connect timeout used by check_ports (matches the source's own 2s timeout). |
pub const DEFAULT_MAX_README_BYTES: usize | Response body byte cap applied when reading readme.html to extract a WordPress version string (Gate 1.5.6 input limit) -- generous headroom for a small static HTML file. |
fn calculate_cookies_score(cookies : & CookieCheckResult) -> u8 | Compute the 0-100 cookie-security score from a CookieCheckResult. |
fn parse_cookie(cookie_str : & str) -> Option <CookieInfo> | Parse a Set-Cookie header value into CookieInfo |
fn extract_wp_version_from_readme(html : & str) -> Option <String> | Extract a WordPress version string ("Version X.X.X") from readme.html's body. |
async fn check_exposed_paths(http : & SafeHttpClient, base_url : & str) -> ExposedPathsCheckResult | HEAD each of SENSITIVE_PATHS against base_url and record any that respond 200/301/302 (403 means "exists but blocked" -- deliberately not counted as exposed; 404 means not found, which is good) |
async fn check_wordpress(http : & SafeHttpClient, base_url : & str,) -> Option <WordPressCheckResult> | Probe xmlrpc.php, the wp-json users endpoint, readme.html, and wp-content/debug.log for WordPress-specific exposure |
async fn check_cookies(http : & SafeHttpClient, url : & str) -> CookieCheckResult | Fetch url and parse its Set-Cookie response headers. |
async fn check_ports(resolver : & TokioResolver, domain : & str) -> PortCheckResult | TCP-connect-probe each of DANGEROUS_PORTS against domain |
fn generate_cookie_issues(cookies : & CookieCheckResult) -> Vec <SecurityIssue> | Generate SecurityIssues from the cookie check result. |
fn generate_port_issues(ports : & PortCheckResult) -> Vec <SecurityIssue> | Generate SecurityIssues from the port check result. |
fn generate_exposed_paths_issues(exposed : & ExposedPathsCheckResult) -> Vec <SecurityIssue> | Generate SecurityIssues from the exposed-paths check result. |
fn generate_wordpress_issues(wordpress : Option <& WordPressCheckResult>) -> Vec <SecurityIssue> | Generate SecurityIssues from the WordPress check result. |
`tls_headers`
| Item | What it is |
|---|---|
pub struct SslCheckResult | SSL/TLS check results. |
pub struct HeadersCheckResult | HTTP security-headers check results. |
pub const DEFAULT_TLS_TIMEOUT: Duration | Default TCP connect + TLS handshake timeout for check_ssl. |
fn calculate_ssl_score(ssl : & SslCheckResult) -> u8 | Compute the 0-100 SSL/TLS score from a SslCheckResult |
fn calculate_headers_score(h : & HeadersCheckResult) -> u8 | Compute the 0-100 HTTP security-headers score from a HeadersCheckResult. |
fn parse_security_headers(headers : & HeaderMap) -> HeadersCheckResult | Parse the security-relevant subset of a response's headers. |
fn generate_issues(ssl : & SslCheckResult, headers : & HeadersCheckResult) -> Vec <SecurityIssue> | Generate SecurityIssues from the SSL and headers check results. |
async fn check_ssl(resolver : & TokioResolver, domain : & str, timeout : Duration,) -> SslCheckResult | Fetch and inspect the peer TLS certificate for domain:443 |
async fn check_headers(http : & SafeHttpClient, url : & Url, max_body_bytes : usize,) -> Result <HeadersCheckResult> | Fetch url and parse its response's security headers, through SafeHttpClient's pinned-resolver egress guard |
Re-exports. Exported here, defined elsewhere.
| Export | Defined in |
|---|---|
{CaaRecord,DmarcPolicy,DnsCheckResult,EmailCheckResult,SpfPolicy} | dns_email::{CaaRecord,DmarcPolicy,DnsCheckResult,EmailCheckResult,SpfPolicy} |
{CookieCheckResult,CookieInfo,ExposedPath,ExposedPathCategory,ExposedPathsCheckResult,PortCheckResult,PortInfo,SameSitePolicy,TechnologyCheckResult,WordPressCheckResult,} | exposed_paths::{CookieCheckResult,CookieInfo,ExposedPath,ExposedPathCategory,ExposedPathsCheckResult,PortCheckResult,PortInfo,SameSitePolicy,TechnologyCheckResult,WordPressCheckResult,} |
{HeadersCheckResult,SslCheckResult} | tls_headers::{HeadersCheckResult,SslCheckResult} |
Boundary
Reaches into foundation.
Shares tier infrastructure with 82 other crates: infrastructure-acquire, infrastructure-adapters-google-calendar, infrastructure-adapters-google-gmail, infrastructure-adapters-google-places, infrastructure-adapters-google-trends, infrastructure-adapters-shodan, infrastructure-adapters-yelp, infrastructure-agent, … (82 total).
_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._
Where it sits
| Tier (ontology) | infrastructure |
| Architectural role (taxonomy) | unclassified (baselined) |
| Location | crates/infrastructure/web-security-audit |
| Vocabulary in force (lexicon) | current |
Tier flow. Which tiers this crate's own edges cross.
flowchart LR n_infrastructure["infrastructure"] --> n_foundation["foundation"]
Dependencies
Runtime, in this workspace.
| Crate | Tier | Optional | Only on |
|---|---|---|---|
| `foundation-web-analysis` | foundation | no | always |
| `infrastructure-fetcher` | infrastructure | no | always |
Runtime, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
async-trait | ^0.1 | — | no | always |
chrono | ^0.4 | serde | no | always |
hickory-resolver | ^0.26 | — | no | always |
regex | ^1 | — | no | always |
reqwest | ^0.12 | json, rustls-tls, stream | no | always |
rustls | ^0.23 | ring | no | always |
serde | ^1 | derive | no | always |
serde_json | ^1 | — | no | always |
thiserror | ^2 | — | no | always |
tokio | ^1 | full | no | always |
tracing | ^0.1 | — | no | always |
url | ^2 | — | no | always |
uuid | ^1 | v4, v7, serde, js | no | always |
webpki-roots | ^0.26 | — | no | always |
x509-parser | ^0.16 | — | no | always |
Development, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
tokio | ^1 | full, full, test-util | no | always |
tokio-test | ^0.4 | — | no | always |
Build. None.
Depended on by. Nothing in this workspace.
Signal flow — what reaches this crate, and what it reaches.
flowchart LR SELF["infrastructure-web-security-audit"] SELF -->|runtime| n_foundation_web_analysis["foundation-web-analysis"] SELF -->|runtime| n_infrastructure_fetcher["infrastructure-fetcher"] classDef self fill:#1f883d,stroke:#1f883d,color:#fff; class SELF self;
Feature flags
No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.
Targets
| Kind | Name | Source |
|---|---|---|
| lib | infrastructure_web_security_audit | `src/lib.rs` |
Error model
No public error type was detected: no public item declares a type named *Error, and no public signature returns one.
Operational characteristics
| Property | Evidence |
|---|---|
| async public surface | yes |
| async runtime | yes |
| database access | none detected |
| network I/O | yes |
| unsafe code | none detected |
| environment variables | none detected |
No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.
Configuration
No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.
Related capabilities
No workspace crate depends on this one.
Verification
| Kind | Count |
|---|---|
| Unit tests | 142 |
| Integration tests | 0 |
| Examples | 0 |
| Doctests | 0 |
Evidence by module. How often each public module is named by something executable.
| Module | Tests | Examples | Consumers |
|---|---|---|---|
crate root | 6 | 0 | 0 |
dns_email | 11 | 0 | 0 |
exposed_paths | 26 | 0 | 0 |
tls_headers | 9 | 0 | 0 |
What the tests establish, by name:
dns_check_result_default—src/dns_email.rsdns_check_serializes_to_json—src/dns_email.rsdns_score_basic_dns_is_thirty—src/dns_email.rsdns_score_dnssec_enabled—src/dns_email.rsdns_score_full_is_100—src/dns_email.rsdns_score_multiple_ns—src/dns_email.rsdns_score_no_dns_is_zero—src/dns_email.rsemail_check_result_default—src/dns_email.rsemail_check_serializes_to_json—src/dns_email.rsemail_score_full—src/dns_email.rsemail_score_no_mx_is_100—src/dns_email.rsemail_score_spf_only—src/dns_email.rsemail_score_spf_plus_all_is_bad—src/dns_email.rsgenerate_dns_issues_no_caa—src/dns_email.rsgenerate_dns_issues_no_dns—src/dns_email.rsgenerate_dns_issues_no_dnssec—src/dns_email.rsgenerate_dns_issues_no_ipv6—src/dns_email.rsgenerate_dns_issues_single_ns—src/dns_email.rsgenerate_email_issues_dmarc_none—src/dns_email.rsgenerate_email_issues_no_dkim—src/dns_email.rsgenerate_email_issues_no_dmarc—src/dns_email.rsgenerate_email_issues_no_mx_means_no_issues—src/dns_email.rsgenerate_email_issues_no_spf—src/dns_email.rsgenerate_email_issues_spf_plus_all—src/dns_email.rsgenerate_email_issues_weak_spf—src/dns_email.rscookie_check_result_default—src/exposed_paths.rscookie_info_serializes_to_json—src/exposed_paths.rscookie_info_struct—src/exposed_paths.rscookies_score_insecure_sensitive_cookie—src/exposed_paths.rscookies_score_no_cookies_is_100—src/exposed_paths.rs- _… 112 more_
Documentation coverage
| Measure | Documented | Total |
|---|---|---|
| Public items with rustdoc | 51 | 62 |
Public modules with a //! block | 3 | 3 |
pie showData
title Public items with rustdoc
"Documented" : 51
"No rustdoc detected" : 11
Metrics
| Metric | Value |
|---|---|
| Rust source files | 4 |
| Source lines | 4382 |
| Code lines | 3663 |
| Public API items | 62 |
| Public modules | 3 |
| Tests | 142 |
| Examples | 0 |
| Cargo features | 0 |
| Direct runtime dependencies | 17 |
| Workspace reverse dependencies | 0 |
pie showData
title Public API by kind
"constant" : 7
"enum" : 6
"function" : 23
"method" : 10
"struct" : 16
pie showData
title Rust source composition
"Code" : 3663
"Blank or comment" : 719
Generation
Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.