PriorAuth Guard

Claims you can check yourself.

PriorAuth Guard evaluates prior authorization packets on the device. That decides the threat model: there is no server holding your packets, so what has to be defended is a stolen laptop and a tampered local record, not a cloud breach. Everything below is stated so a security reviewer can verify it in a browser rather than take our word for it.

Last verified September 3, 2026 Against the deployed build at priorauthguard.com/app/

Two claims this page proves as you read it.

The rest of this page is prose, and prose is easy to write. These two boxes run in your browser and print what they actually find. If either one disagrees with the text below it, believe the box.

Requests made by this page

Measuring.

The claim is zero requests to any other origin: no fonts, no analytics, no tag managers, no CDN. The list is this page's own requests, with the origin trimmed off. One of them is the check on the right, reading the policy header.

Content-Security-Policy header

Checking.

A report-only policy logs violations and permits them. The claim is that this site is served enforcing, so the browser blocks anything the policy forbids instead of merely noting it.

Four cryptographic pillars, all offline.

Each one addresses a specific way a device holding patient documentation can be turned against the team using it.

Pillar 01

Encryption at rest, with the key derived from a passphrase

Every local store, packets, documents, audit log, receipts and rule packs, is opened through an AES-256 cipher. Where that key lives is the part that matters. On a native build the operating system keychain holds it. In a browser there is no keychain, and the storage plugin falls back to the same store the encrypted data sits in, which would put the key and the ciphertext side by side under adjacent names.

So the key is not kept. A random 256-bit master key encrypts the data, and that master key is itself sealed under AES-256-GCM with a key derived from the operator's passphrase. Only three things are written to the device: a random salt, the derivation cost parameters, and the sealed envelope. None of them decrypt anything without a passphrase that exists solely in someone's head. Changing the passphrase re-seals the envelope and rewrites no packets.

Because no key exists until the passphrase is typed, the app stops at an unlock screen before it opens a single store. There is also deliberately no fast verifier written to disk: the AES-GCM authentication tag is the verifier, so an attacker with the device gets no cheap way to test guesses offline.

Pillar 02

Tamper-evident audit chain

Every evaluation appends an entry to a hash chain, where each entry's hash covers a canonical form of the record plus the hash before it, keyed by a device secret. Editing, deleting or reordering any entry breaks the chain from that point forward.

The integrity check recomputes the whole chain and names the first entry that no longer matches, so a log cannot be quietly adjusted after the fact to hide a missing document or a billing omission. Exports carry the verified chain head so a third party can re-check them outside the app.

Pillar 03

Signed rule updates

Payer rules change, so the app can fetch updated rule packs. That fetch is the only code in the app that touches the network, and it is one-way: a GET, with nothing uploaded.

Rule packs arrive as Ed25519-signed envelopes and are rejected unless the signature verifies against the public key built into the app, before the schema validator ever sees the contents. A hostile network can withhold an update or serve an old one. It cannot inject altered clinical constraints.

Pillar 04

Signed completion receipts

When a packet review completes, the receipt is Ed25519-signed with a per-device key rather than merely hashed, which makes it verifiable by someone who did not generate it.

Alongside this, the app locks itself after five minutes idle or when backgrounded, clearing the in-memory pointer to the open packet. Integrity verification for the chain and the receipts can be run on demand from Settings, under Security.

The primitives, with their actual settings.

Nothing here is a custom construction. These are standard primitives at published parameters, listed so a review does not have to ask.

Purpose Primitive Parameters
Data at rest AES-256 Every local store, with a one-time migration of any store written before encryption was in place
Sealing the master key AES-256-GCM Random nonce per seal; the authentication tag doubles as the passphrase verifier, so no separate verifier is stored
Passphrase derivation PBKDF2-HMAC-SHA256 600,000 iterations, 256-bit output, random per-device salt. Runs through the browser's native WebCrypto, about 450 ms on a current laptop
Audit chain HMAC-SHA256 Append-only, keyed by a device secret, over a canonical serialization of each record
Receipts and rule packs Ed25519 Receipts signed per device; rule packs verified against a public key embedded in the app, with the private key never on a device
Hashing input Canonical JSON Deterministic key order and encoding before any hash or signature, so the same record always produces the same digest

On the derivation cost: Argon2id is the stronger choice on paper and was built first, then measured and removed. The library available here has no browser-native Argon2, so in a browser it runs as compiled Dart, where a 2 MiB memory parameter took 24,957 ms in testing, a cliff rather than a curve. At the recommended parameter the app would have appeared frozen for half a minute on every launch. PBKDF2 goes through the browser's own WebCrypto implementation instead, which is how 600,000 real iterations cost under half a second. The stored parameters include which algorithm produced them, so a future build can move without stranding an existing device.

One outbound request, and it carries nothing of yours.

Two details a careful reviewer will find, stated here rather than left to discovery. The rendering engine asks for a fallback font whenever text contains a character no bundled typeface covers, which real patient names can trigger; that request is pointed at this origin, so the character renders as a blank box instead of becoming a request to Google. And the access request form on the marketing pages emails an address you type into it. That form is not part of the app, it never sees packet data, and its policy forbids a native form submit precisely so an address cannot end up in a URL.

What this does not claim.

A security page that lists only strengths is not much use in a review. These are the limits, in the same detail as the claims.

How to check every claim above.

None of this requires our cooperation, a demo environment or an NDA. A reviewer with a browser can confirm the whole page in about ten minutes.

  1. Confirm nothing goes to a third party.

    Open /app/ with the Network tab recording, then work through a packet. Sort by domain. Every request should be to this origin.

  2. Read the policy header yourself.

    Request any page here and read the response headers. Content-Security-Policy should be present with default-src 'self', and there should be no report-only header alongside it.

  3. Look for the key.

    With a passphrase set, inspect local storage for the app's origin. The vault entries are the salt, the cost parameters and the sealed envelope, in keys ending kv_salt, kv_kdf and kv_sealed_master (the storage plugin prefixes its own name). There is no key material and no password hash. Before a passphrase is set you will also find the device key, which is the state the previous section describes.

  4. Check a rule pack signature.

    Fetch /rules/payer-rules.signed.json. It is public on purpose. Verify its Ed25519 signature, then alter one byte and watch the app reject it.

  5. Break the audit chain on purpose.

    Run a few evaluations, edit or remove a stored audit entry, then use Settings, Security, Verify Data Integrity. It should name the first entry that no longer matches.

  6. Pull the network.

    Go offline and reload /app/. The app is installable and precaches its own shell, so a review can confirm it works with no connection rather than trusting the word offline.

If any step comes out differently than described, that is a defect and we want to hear about it. Mail James@execlayer.io with what you ran and what you saw.

Run it against a real packet path.

Open the app in a browser and check the claims on this page as you go, or schedule a pilot conversation to work through rule ownership, signed updates and where this fits in your existing controls.