Product · audits

Automated Website Evidence Audit

Seven observable technical domains plus an evidence-linked remediation ledger. Interaction testing is not included.

Inputs and outputs

You supply

  • One public URL to start from
  • Optional list of additional public URLs on the same origin
  • Optional list of paths to exclude

You receive

  • Desktop and mobile render evidence at fixed viewports
  • Machine-checkable accessibility findings mapped to WCAG 2.1 where applicable
  • Technical SEO and metadata inventory for checks this definition implements
  • Third-party request and storage inventory
  • Asset integrity results for requested subresources
  • Link and navigation resolution results with HTTP status per target
  • Browser console and page error transcript
  • Explicit not_covered list including the entire interactions domain
  • Prioritized remediation ledger with severity and evidence references

When checkout opens, the entire purchase is a URL, a payment, and a download link. There is no intake form, no scoping call, and no questionnaire, because the scope is fixed and published on this page.

What this is

A run against a public website that records what a real browser engine actually does with it — at a desktop viewport and a mobile viewport — and files the result as evidence. Seven observable technical domains plus an evidence-linked remediation ledger. Interaction testing is not included. Interaction probes are published as not_covered and are not part of the offer. Every finding names the artifact that produced it and a stable check_id. The report ends in an ordered list of work rather than a score.

It is deliberately narrow. It reads a site and reports. It does not log in, it does not submit anything, it does not drive the keyboard, it does not change anything, and it does not guess. Checks the runner does not implement are listed as not covered rather than implied by silence.

What you get back

Two files. A static HTML report that opens in a browser with no network access required, and a JSON document with the same content in machine-readable form so it can be diffed, filed, or fed into your own tooling. Both are self-contained. Both carry the runner version, the browser engine version, and the audit definition version that produced them, so a report from six months ago can be explained.

What it will not do

The boundaries below are the product. They are published here rather than buried in terms, because the reason to trust an unattended process is knowing exactly how far it is allowed to go.

Seeing one before checkout opens

Checkout is not open, so there is nothing to buy on this page yet. There is a private demo: a code-gated route that runs the real pipeline and hands back the real package. It is not a signup and there is nothing to fill in unless you already hold the admin code, which is given out one conversation at a time.

Why there is no score

A single number sums unrelated evidence into something that cannot be acted on and can always be argued with. Instead the report ends in a ranked ledger: grouped by cause, ordered by severity and by how many routes each item affects, with every entry pointing back at the artifact that justifies it. The point of the run is to end in a decision about what to do next.

9 evidence domains · definition v1

Every check, every artifact, every limit

Expand a domain to read exactly what is examined, what is kept as proof, and what the domain does not cover.

Desktop and mobile rendering partial · 5 checks

Record what a real browser engine paints at fixed viewports, so layout claims are settled by an image and a measurement rather than by memory.

Checked

  • rendering.full_page_capture (implemented · capture) — Full-page capture at desktop 1440x900 and mobile 390x844
  • rendering.horizontal_overflow (implemented) — Horizontal overflow measured as scrollWidth against clientWidth
  • rendering.text_below_minimum_size (implemented) — Minimum rendered text size per text node against a published floor
  • rendering.elements_clipped_or_overlapping (not_covered) — Elements clipped or overlapping at either viewport
  • rendering.layout_shift_late_assets (not_covered) — Layout shift caused by late-loading local assets

Evidence kept

  • Screenshot per route per viewport
  • Measured document and element geometry as JSON

Not covered

  • One browser engine, stated by name and version in the report
  • No visual judgement of taste, hierarchy, or brand fit
  • No emulation of assistive hardware or real devices
Accessibility partial · 12 checks

Check the machine-checkable part of WCAG 2.1 AA and say plainly that the rest still needs a person.

Checked

  • accessibility.missing_h1 (implemented) — Missing h1 on a captured route
  • accessibility.multiple_h1 (implemented) — More than one h1 on a captured route
  • accessibility.heading_level_skipped (implemented) — Heading order skips a level
  • accessibility.link_without_accessible_name (implemented) — Link without an accessible name
  • accessibility.image_missing_alt (implemented) — Image alternative text missing where required
  • accessibility.contrast_below_aa (implemented) — Text contrast ratio below WCAG 2.1 AA against resolved colours
  • accessibility.missing_document_language (implemented) — Document language attribute missing
  • accessibility.missing_document_title (implemented) — Document title missing
  • accessibility.landmark_and_skip_link (not_covered) — Landmark structure and skip-link target resolution
  • accessibility.visible_focus_indicator (not_covered) — Visible focus indicator on every keyboard-reachable control
  • accessibility.reduced_motion (not_covered) — Reduced-motion handling for animated elements
  • accessibility.button_and_control_names (not_covered) — Accessible names for buttons and form controls beyond links

Evidence kept

  • Per-finding CSS selector and DOM snippet
  • Computed contrast ratio with both resolved colour values
  • Mapping to the specific WCAG 2.1 success criterion where applicable

Not covered

  • Automated checks cover a minority of WCAG 2.1 criteria
  • No screen-reader output is simulated or scored
  • Cognitive, language, and content-comprehension criteria are out of scope
  • A clean automated result is not an accessibility conformance claim
  • Translucent colours are skipped rather than approximated
Technical SEO and metadata partial · 9 checks

Inventory the machine-readable claims a page makes about itself and flag the ones that contradict each other.

Checked

  • seo.duplicate_title (implemented) — Document title duplicated across captured routes
  • seo.missing_meta_description (implemented) — Meta description tag missing on a captured route
  • seo.robots_txt_without_sitemap (implemented) — robots.txt reachable without a Sitemap directive
  • seo.canonical_url (not_covered) — Canonical URL presence and self-consistency
  • seo.opengraph_twitter_cards (not_covered) — OpenGraph and Twitter card completeness
  • seo.structured_data (not_covered) — Structured data presence and JSON parse validity
  • seo.title_description_length (not_covered) — Title and meta description length scoring
  • seo.sitemap_route_agreement (not_covered) — Sitemap contents fetched and compared to discovered routes
  • seo.heading_outline_link_depth (not_covered) — Heading outline and internal link depth as an SEO inventory

Evidence kept

  • Extracted title presence and uniqueness across routes
  • Meta description presence per route
  • robots.txt text as recorded in the scope record

Not covered

  • No rank, traffic, difficulty, or competitor estimates
  • No keyword recommendations
  • Search engines are not queried; only the site is read
  • Description body text is not persisted by the current DOM summary
Privacy and third-party surface partial · 8 checks

Record what the page contacts and what it stores, so the privacy policy can be compared against observed behaviour.

Checked

  • privacy.third_party_origin (implemented) — Every outbound request grouped by third-party origin
  • privacy.third_party_script (implemented) — Third-party executable script requests recorded
  • privacy.cookie_set_on_load (implemented) — Cookies present after load, by name and attributes, never by value
  • privacy.web_storage_written_on_load (implemented) — localStorage and sessionStorage key names present after load
  • privacy.insecure_transport (implemented) — Transport security of every request
  • privacy.blocked_by_audit_policy (implemented) — Requests the audit runner itself refused, with the reason
  • privacy.tracker_classification (not_covered) — Classification of origins as analytics, tag-manager, or advertising
  • privacy.consent_gated_behaviour (not_covered) — Behaviour after a consent interaction (consent UI is not exercised)

Evidence kept

  • Request ledger with origin, resource type, and initiator
  • Storage ledger with key names and attributes

Not covered

  • Observed behaviour on the audited routes only, at run time
  • No legal opinion on GDPR, CCPA, or any other regime
  • Server-side data handling is invisible to this audit
  • Cookie and storage values are never read
Asset integrity partial · 4 checks

Prove that every local asset the page references actually resolves, because a green build does not.

Checked

  • asset-integrity.request_failed (implemented) — HTTP status recorded for every subresource the page requested
  • asset-integrity.unexpected_content_type (implemented) — Response content-type compared against the requested resource type
  • asset-integrity.unrequested_markup_references (not_covered) — Assets referenced in markup but never requested during the load
  • asset-integrity.favicon_manifest_social (not_covered) — Favicon, manifest, and social-card image reachability as dedicated checks

Evidence kept

  • Asset ledger with source reference, resolved URL, and status from the request ledger

Not covered

  • Reachability and content type only; no image quality assessment
  • Third-party asset availability is recorded, not guaranteed
  • Requests with no recorded response are not asserted as failures
Browser console and page errors partial · 6 checks

Capture the errors a visitor's browser already reports and nobody reads.

Checked

  • console.page_error (implemented) — Uncaught JavaScript exceptions with message text
  • console.error (implemented) — Console error entries during the observed load
  • console.warning (implemented) — Console warning entries during the observed load
  • console.failed_network_requests (not_covered) — Failed network requests ranked inside the console domain
  • console.csp_violations (not_covered) — Content Security Policy violation reports as a separated class
  • console.mixed_content_blocked (not_covered) — Mixed-content and blocked-resource events as a separated class

Evidence kept

  • Timestamped console transcript per route and viewport

Not covered

  • Errors raised during the observed load window only
  • Errors behind authentication or user-specific state are not reached
  • Console log, info, and debug entries are recorded but not ranked
  • Stack frames beyond the reported message text are not persisted
Interaction probes not_covered · not sold · 6 checks

Exercise the parts of a page that only misbehave once touched.

Checked

  • interactions.keyboard_traversal_order (not_covered) — Keyboard traversal order against visual order
  • interactions.focus_visibility_sequence (not_covered) — Focus visibility at every stop in the tab sequence
  • interactions.disclosure_menu_dialog_keyboard (not_covered) — Disclosure, menu, and dialog controls opened and closed by keyboard
  • interactions.focus_return_after_close (not_covered) — Focus return after a dialog or menu closes
  • interactions.hover_only_affordances (not_covered) — Hover-only affordances that have no keyboard equivalent
  • interactions.layout_stability_during_transition (not_covered) — Layout stability during and after transitions

Evidence kept

  • None in this definition version — no probe transcript is produced

Not covered

  • Interaction probes are not implemented in this definition version
  • The capture runner observes a page load and does not drive the keyboard
  • No form submission, account creation, purchase, upload, or other state-changing request is ever performed
  • Because no probe ran, an empty result for this domain is not evidence that interactions behave correctly
  • Flows requiring credentials are never attempted
Prioritized remediation ledger covered · 5 checks

Turn findings into an ordered list of work, so the report ends in a decision rather than a feeling.

Checked

  • remediation.severity_from_rubric (implemented · process) — Severity assigned from the published rubric in data/report_schema.yaml
  • remediation.group_by_shared_cause (implemented · process) — Findings grouped by shared cause so one fix closes one ledger entry
  • remediation.link_evidence (implemented · process) — Each ledger entry linked back to the findings and artifacts that produced it
  • remediation.order_severity_then_breadth (implemented · process) — Ordering by severity, then by breadth of affected routes
  • remediation.mark_human_review (implemented · process) — Items that a machine check cannot close are marked for human review

Evidence kept

  • Ordered remediation table with severity, affected routes, and evidence IDs

Not covered

  • Effort and cost estimates are not produced
  • No code changes are written, proposed as patches, or applied
  • Business priority is yours; the ledger orders by evidence only

Crawl budget · wea-v1-crawl-budget · definition v1

Published crawl budget

These are the numeric limits the runner enforces. The sold product uses the API path numbers. The operator CLI ships different defaults for local runs; that difference is intentional and stated here so it is not a surprise.

Enforced limits
LimitSold product (API)Operator CLI default
Maximum in-scope routes2550
Maximum total HTTP requests20002000
Maximum redirect hops55
Minimum request interval (cooldown)0.5 seconds0.5 seconds
Wall-clock timeout900 seconds (API job / crawl ceiling)300 seconds
Crawl transfer-byte cap67108864 bytes (64 MiB aggregate declared responses)67108864 bytes
Persisted artifact-byte cap134217728 bytes (128 MiB)134217728 bytes
Per-request timeout45 seconds45 seconds
API job queue depth4n/a (CLI is single-run)
Ownership challenge rate limits5 per host / 20 global per 3600s windown/a

Viewports: desktop 1440×900 and mobile 390×844. robots.txt is respected by default. Buyers cannot raise these limits at purchase. Truncation and not-reached routes are recorded in the report.

Report schema · v1 · frozen

The output format, frozen at version 1

The machine-readable half of a report is a single JSON document. Its shape was published here before the code existed, then frozen (wea-v1-report-schema-freeze) so consumers can rely on required fields. The derivation engine is held to it by contract tests that derive a real report and check every required field below. Within version 1 only additive optional fields are allowed. A breaking change gets a schema_version bump and an entry in the launch log.

Top-level document fields
FieldTypeRequiredDescription
schema_versionintegeryesVersion of this document schema. Increments on any breaking change.
report_idstringyesOpaque identifier for the run, unique per audit.
generated_atstring (RFC 3339)yesUTC timestamp at which the run completed.
targetobjectyesThe audited origin, the entry URL, and the resolved route list.
runnerobjectyesBrowser engine name and version, runner version, and audit definition version.
scopeobjectyesCrawl budget, viewports used, routes visited, and routes deliberately excluded.
domainsarray of objectyesOne entry per evidence domain, each carrying its own findings and limits.
findingsarray of objectyesFlat list of every finding, referenced by the remediation ledger.
remediationarray of objectyesOrdered remediation ledger.
artifactsarray of objectyesEvery screenshot, transcript, and ledger produced, with a content hash.
not_coveredarray of stringyesExplicit list of what this run did not examine, and why.
summaryobjectnoFinding and remediation counts, and counts per severity. Derived from the lists below; carried so a reader does not have to recount them.
Finding object
FieldTypeRequiredDescription
idstringyesStable within a report; referenced by remediation entries.
domainstringyesOne of the nine evidence domain identifiers.
severitystringyesOne of the severity levels below, assigned by rubric.
titlestringyesOne line stating what was observed, not what it implies.
observedstringyesThe measurement or event exactly as recorded.
expectedstringyesThe rule that was applied, and where that rule comes from.
routesarray of stringyesRoutes on which the finding was reproduced.
selectorstringnoCSS selector for the element, where the finding is element-scoped.
artifact_idsarray of stringyesArtifacts proving the finding. A finding with none is not emitted.
verified_bystringyesmachine — every published finding is machine-verified.
check_idstringnoNamespaced identifier of the rule that produced this finding, as domain.check. Stable across reports; use it to track one defect over time.
statusstringnoOne of the status values below. Defaults to reproduced.
viewportsarray of stringnoViewports the finding was reproduced at, where it is viewport-specific.
actionstringnoWhat to change, stated as an outcome. Repeated on the remediation entry that groups this finding.
needs_human_reviewbooleannoTrue when the finding records something a machine cannot judge — a third-party origin that may be intended, a cookie that may be necessary.
Remediation ledger entry
FieldTypeRequiredDescription
rankintegeryesPosition in the ledger, ascending.
finding_idsarray of stringyesFindings resolved by this item; grouped by shared cause.
severitystringyesHighest severity among the grouped findings.
affected_routesintegeryesCount of routes on which the grouped findings appear.
actionstringyesWhat to change, stated as an outcome rather than as a patch.
needs_human_reviewbooleanyesTrue when the item cannot be closed by a machine check alone.
group_keystringnoThe shared cause that grouped these findings. Two symptoms with one key are one fix.
artifact_idsarray of stringnoEvery artifact cited by the findings this entry groups.

Severity rubric

Severity is assigned from these definitions. No finding is escalated because it sounds serious, and none is softened because it is awkward.

blocking
Observed behaviour prevents a documented task from completing at all for some visitors — a keyboard trap, an unreachable control, a 5xx on a route linked from the entry page.
serious
Observed behaviour degrades a documented task or violates a stated contract — a WCAG 2.1 AA failure, a broken internal link, an asset that does not resolve, an uncaught exception on load.
moderate
Observed behaviour is incorrect but has a working path around it — a redirect chain, a duplicated title, a missing canonical URL.
minor
Observed behaviour is inconsistent with the site's own conventions and carries no known user-facing impact.
informational
Recorded for the ledger with no defect asserted — a third-party origin inventory entry, a redirect that behaves as intended.

Finding status values

reproduced
Observed on every attempt within the run.
intermittent
Observed on some attempts; attempt count is recorded.
not_reached
In scope but unreachable — authentication, rate limit, or timeout.
excluded
Deliberately outside the run's stated scope.

Hard automation boundaries

What the runner is never allowed to do

These limits are enforced in the runner, not promised in prose. Anything on this list occurring during a run is a defect, and would be reported as one.

  • The runner never authenticates.

    No credentials are accepted, stored, or used. Anything behind a login is out of scope and is reported as not reached, never as passing.

  • The runner never performs a state-changing request.

    No form submissions, no purchases, no uploads, no account creation, no requests outside safe HTTP methods against the audited origin.

  • The runner never writes to your infrastructure.

    No files, no DNS records, no repository commits, no configuration changes. The audit reads and reports; you decide what to change.

  • A finding without an artifact is not published.

    Every entry in the report references the screenshot, header, console line, or DOM assertion it came from. If the artifact is missing, the finding is dropped rather than described.

  • Severity comes from a published rubric.

    Severity is assigned by rule, not by how alarming a finding sounds. The rubric is published in the standards page and versioned with the report.

  • No single overall score is produced.

    Composite scores compress unrelated evidence into one number that cannot be acted on. The report ends in an ordered list of work instead.

  • Audit output is never sold, aggregated, or published.

    Reports belong to the buyer. Nothing from a run is used as a case study, a benchmark, or training data without a separate written agreement.

  • The runner never load-tests, floods, or brute-forces.

    Requests are rate-limited and bounded by a stated crawl budget. The audit is designed to be indistinguishable from a careful visitor.

  • The runner never probes for vulnerabilities.

    No injection attempts, no path traversal, no credential testing. This is an evidence audit, not a penetration test, and it is not a substitute for one.

Where a person is still required

An unattended product that pretends to cover these would be lying by omission. Each is named in the report itself, next to the results.

  • Accessibility conformance statements.

    Automated checks find a minority of WCAG 2.1 issues. A conformance claim requires manual testing with assistive technology; this product does not make one and neither should a report derived from it.

  • Legal and regulatory interpretation.

    The privacy domain records observed behaviour. Whether that behaviour complies with any given regulation is a question for a lawyer.

  • Content quality and editorial judgement.

    Whether a page says the right thing to the right reader is not a machine question and is not answered here.

  • What to fix first, commercially.

    The ledger orders by evidence and breadth. Only you know which route earns the revenue.

  • The fixing itself.

    No code is written, patched, or deployed on your behalf as part of an audit.

Not buyable yet

Checkout is not open, there is no waitlist form, and no price is published. The launch page lists the gates that have to close first, and the launch feed records each one as it does.

Launch status and gates The standards behind this