Developers
Root Herald in three calls
Your backend holds the only key. A keyless client on the device answers a challenge; your backend appraises the answer and gets the verdict back on the same call.
server (Node) — the whole APIts
import { RootHeraldClient } from "@rootherald/node";
const rh = new RootHeraldClient({ secretKey: process.env.RH_SECRET_KEY! }); // rh_sk_…
// 1. Mint a challenge. It carries the nonce, the ask, and the policy.
const { challengeId, challenge } = await rh.issueChallenge({
ask: ["identity", "posture"], // or ["key"] to mint a device-bound key
policy: "rootherald:builtin:strict-hardware",
});
// 2. Relay `challenge` to the device verbatim; it answers with an opaque `evidence` blob.
// 3. Appraise it. A failing device is a verdict, not an exception.
const result = await rh.verify(evidence, { challengeId });
result.enrollmentRequired; // first contact → relayEnroll / relayActivate, then verify again
result.device.verdict; // "pass" | "warn" | "fail"
result.device.ueid; // stable per-tenant device id, no PII
result.key?.jwk; // only for a key ask, only on passWhat it is
- A device proves it is a specific, real chip: a TPM 2.0 quote on Windows and Linux, the Secure Enclave on macOS, App Attest on iOS.
- Every proof answers a single-use
challengeyour backend minted, so it cannot be replayed. - The challenge says what to prove (the ask:
identity,posture,key) and which policy judges it. - The client holds no Root Herald key and never talks to Root Herald; it returns an opaque blob.
- Your backend submits the blob with its
rh_sk_key and gets a verdict on that call. No token, no JWKS. - First contact on a machine is a one-time, two-leg enrolment that binds an attestation key inside the chip. Windows needs one elevation for it; nothing afterwards does.
- The verdict carries a stable per-tenant device id, an EAR status, boot booleans, assurance claims, and optionally a certified public key.
- A
keyask mints an ECC P-256 key that cannot leave the chip; later requests are signed with it and verified locally with no Root Herald call. - Policies are named on the challenge and can be tightened at verify but never loosened.
- Errors are string codes on a 4xx; a device that fails policy is a 200 with a failing verdict.
Guides
Quickstart
Enrol and verify a device end to end with @rootherald/node and @rootherald/browser.
Enrolment
The two-leg ceremony, admission under a policy, and the per-tenant device id.
Challenges and verdicts
The three asks, the challenge string, and every verdict field.
Policies
The five built-ins, every knob, custom policies, and cohort prevalence.
App keys
Mint a device-bound key, sign requests, verify them locally.
Re-attestation and step-up
Attest-first, enrol on miss, and a fresh posture check before a sensitive action.
Webhooks
Verdicts, enrolments and usage alerts on your own endpoint.
Clients
The server half is the same everywhere. Pick where the evidence is collected:
SDKs
Node.js
Available@rootherald/node · server
Browser
In development@rootherald/browser · client
Native C
In developmentRootHerald.lib / librootherald.a · client
All SDKs → — Go, Java, PHP, Ruby, .NET, iOS, and the native status codes.