Darin Molnar, PhD · June 8, 2026 · 5 min read

Why we built the verifier as a browser-only WebAssembly app

Cryptographic verification has a credibility problem on the web. WebAssembly is how we solved it without making customers install a CLI.

There’s a subtle credibility problem with running cryptographic verification on a website. The website tells you the verification succeeded, but the verification also ran on the website’s server. So you’re trusting the website to tell you the truth about its own verification. That defeats the entire point.

Most “verify your document online” tools have this problem, and they handle it by hand-waving past it. You upload your file, the server runs the math, the server reports the result, you take the server’s word for it. Fine if you trust the server. Catastrophic if the server has any reason to lie. For our product — where the whole story is “you don’t have to trust us; the math does the trusting” — this trade-off was a non-starter.

The two honest options are (1) run the verification on the user’s own machine via a locally-installed tool, or (2) run it in the user’s browser via JavaScript or WebAssembly. We’ve shipped option (1) since the beginning: athena-verify is an open-source binary that compiles from the same Rust crate that runs in our server-side audit subsystem. Anyone can install it, inspect its source, and verify a Decision Record entirely offline. That’s the auditor’s path.

But option (1) doesn’t help the lender’s underwriter, the AMC reviewer, or the borrower’s attorney who just received a Record file and wants to confirm it’s real. They’re not going to cargo install athena-verify. We needed a path that runs in a browser tab, and we needed it to be honest about who’s doing the cryptographic work.

The WebAssembly answer

WebAssembly compiles our existing Rust verifier crate to a binary that runs in the browser’s WASM runtime. The cryptographic math — SHA-256 hashes, ECDSA signature verification, RFC 3161 timestamp validation, canonical-JSON re-derivation — runs in the user’s browser process, on the user’s CPU, with no server-side step. The page tells you it verified your record because the page’s code actually ran the verification on your machine. The result is honest because the verification is local.

There are three security properties that make this work as a credibility story:

  1. The cryptographic primitives are RustCrypto crates already battle-tested in the audit subsystem. Same sha2, ecdsa, and p256 crates that produce the seals are the ones that verify them. No reimplementation, no second copy of the math to keep in sync.
  2. The WebAssembly bundle is inspectable. A skeptical auditor can download the .wasm file, run it through a disassembler, verify it does what we say it does, and confirm the JavaScript that loads it doesn’t tamper with the inputs or outputs. That’s the trade we’re making in exchange for browser convenience: not “trust the page,” but “trust the page after you’ve checked the page.”
  3. We publish the bundle’s SHA-256 checksum. The same Rust source code, compiled with the same toolchain, should produce a bundle with the same hash. An auditor can build from source, compute the hash, compare to ours, and confirm the bundle they’re seeing in the browser matches the open-source code. If the hashes diverge, something is wrong.

Why this isn’t possible with regular JavaScript

It is, technically — you can implement SHA-256 and ECDSA P-256 in JavaScript. People have. But you’re then maintaining a separate JavaScript implementation of cryptographic primitives that has to match a separate Rust implementation, and any divergence between them is a security bug. WebAssembly lets us ship one implementation, written once, audited once, used both server-side and client-side. The browser is just another execution target for the same code.

That last point matters more than it sounds. The Rust verifier crate that runs server-side in the audit subsystem and the WASM verifier that runs client-side in the browser are the same code, modulo the wasm-bindgen interface layer. When we fix a bug or improve the verification logic, both sides get the fix simultaneously. There’s no JavaScript reimplementation drift to worry about.

Why we’re shipping this as a separate web app

The web verifier lives at verify.athenanorthstar.com, not as a subroute under our marketing site or our product application. There are two reasons.

First, separation of concerns. The marketing site is for prospects; the product application is for paying customers; the verifier is for anyone (mostly non-customers) who’s received a Record and wants to verify it. Each surface has a different audience and a different operating model. Mixing them dilutes the verifier’s “this is the trustworthy independent verification tool” framing.

Second, deployment independence. The verifier needs to be deployable with no dependency on the rest of our infrastructure — no shared authentication, no shared analytics, no shared CDN that could be redirected away. It’s a flat-file static site (HTML + JS + WASM + a directory of public-key JSON files) that could in principle be deployed to any static host, even mirrored by third parties if there were ever a reason. That’s the verification-tool equivalent of “no single point of failure for trust.”

What the verifier does NOT do

A few things worth being explicit about, because the web verifier is the first thing a non-technical customer interacts with:

  • It doesn’t upload your Record to our servers. The file you drag onto the page is read locally by the browser. We don’t see it, we don’t log it, we don’t store it.
  • It doesn’t track you. No analytics, no cookies, no fingerprinting. The verifier page is a privacy-respecting verification surface; we owe that to the audience because the audience is sometimes verifying a Record specifically because they’re skeptical of someone.
  • It doesn’t claim the underlying appraisal is correct. Same framing as the Decision Record itself: the seal is an evaluation-event witness, not a content attestation. Reading the verifier output tells you the math worked. Reading the underlying appraisal — the URAR, the comps, the adjustments — is a separate exercise in human professional judgment.

The web verifier is the customer-facing front door for verification. The CLI is the auditor’s deep-inspection tool. They’re two delivery vehicles for the same cryptographic primitive, and the web verifier is honest about being one because it makes its inspectability and its non-tracking claims load-bearing in the experience.

That’s the design. Build is in progress; we’ll ship in the first weeks after launch.

About the author

Darin Molnar, PhD — CTO · President · Founder. Darin built the rule engine, the cryptographic audit chain, the web application, and the marketing site. He's the technical authority on every layer of the stack.

Read more from Darin Molnar at /blog/author/darin/ .

Related notes