RootHerald.AspNetCore
The server→server Background-Check client for ASP.NET Core. Mint a challenge, appraise the client's opaque evidence with your rh_sk_ secret key, and get the verdict back directly in the response. Pure managed C# over HttpClient, no native dependencies. Targets .NET 8 LTS and .NET 9.
This SDK is implemented but not yet published to its package registry. Until it ships, collect an opaque evidence blob on the device and appraise it server-side with @rootherald/node (or any available server SDK). The API shown below is the planned surface and may change before release.
How it works
Your keyless client collects an opaque evidence blob and hands it to your backend. Your backend uses RootHeraldBackgroundCheckClient, authenticated with its rh_sk_ secret, to mint a nonce (IssueChallengeAsync) and submit the evidence for appraisal (VerifyAsync). The verdict is computed by Root Herald and returned to your backend — it never travels through the client, which holds no key.
Install
dotnet add package RootHerald.AspNetCoreConstruct the client
using RootHerald.AspNetCore;
// Register once (e.g. as a singleton). rh_sk_… is your secret key; a value
// that doesn't start with rh_sk_ is rejected. Pure managed C# over HttpClient.
var rh = new RootHeraldBackgroundCheckClient(
Environment.GetEnvironmentVariable("RH_SECRET_KEY")!);Mint a challenge
// Mint a nonce and relay it to your client; it quotes over challenge.Nonce
// and returns an opaque evidence blob to your backend.
RootHeraldChallenge challenge = await rh.IssueChallengeAsync();Verify the evidence
VerifyAsync returns an AttestResult: a normalised Verdict string, IsAllowed, and the full VerdictData as a JsonNode (which also carries the advisory-only cohort fields when a quote-bound event log was supplied).
using System.Text.Json.Nodes;
// 'evidence' is the opaque blob your client collected, as a JsonNode; it is
// passed through verbatim. Only protocol/auth/quota problems throw a
// RootHeraldApiException — a failing device does not.
AttestResult result = await rh.VerifyAsync(evidence, new AttestOptions
{
ChallengeId = challenge.ChallengeId,
Policy = "rootherald:builtin:strict-hardware",
});
if (!result.IsAllowed) // Verdict is "allow" | "deny" | "review"
return Results.StatusCode(403);
// The full verdict is on result.VerdictData; read the stable device id from it.
string? deviceId = result.VerdictData["device"]?["ueid"]?.GetValue<string>();The client also relays the one-time device-key bootstrap via RelayEnrollAsync / RelayActivateAsync. Protocol/auth/quota failures throw the typed RootHeraldApiException taxonomy (InvalidSecretKeyException, UnknownPolicyException, QuotaExceededException, …); a real-but-rejected device is not an exception. A runnable RootHerald.AspNetCore.Sample project ships in the SDK repo.