grundnorm
v0.1.1
Published
Official SDK for the Grundnorm grounded source-of-law truth layer — resolve a legal norm by open identifier (ELI/ECLI) + date and verify its cryptographic seal locally.
Maintainers
Readme
grundnorm (TypeScript SDK)
Resolve a legal norm by its open identifier (ELI/ECLI) and a date, and get back its canonical, sealed meaning as an independently verifiable signed object. The SDK recomputes the content hash and verifies every Ed25519 signature locally — you never have to trust the server.
- Deterministic, zero-LLM read path. Honest
not_foundinstead of a guess. - Point-in-time:
[validFrom, validUntil)— "what did the law say on day X". - Node.js 20+. Zero runtime dependencies.
Install
npm install grundnormUse
import { GrundnormClient } from "grundnorm";
// Defaults to the public GDPR demonstrator. For a pilot, pass your endpoint + metered nlk_ key:
// new GrundnormClient({ endpoint: "https://.../api/grundnorm/resolve", apiKey: "nlk_..." })
const client = new GrundnormClient();
const r = await client.resolve({
id: "http://data.europa.eu/eli/reg/2016/679/art_5",
jurisdiction: "EU",
at: "2026-07-07", // omit for "today"
});
if (r.status === "found") {
console.log(r.norm.atoms); // subject / modality / action / condition / exception / scope + evidence
console.log(r.verification?.ok); // true only if hash recomputes AND all signatures verify
}resolve() verifies the seal by default. Skip it with { verify: false }, or verify a stored
envelope later:
import { verify } from "grundnorm";
const v = verify(norm); // { ok, hashOk, viewConsistent, recomputedHash, signatures[], quorum }v.ok is the one signal to trust. It is true only when ALL of these hold — inspect the
component fields for anything less:
How verification works (no trust required)
- Hash:
sha256(canonicalize(norm.canonical.content))equalsnorm.seal.contentHash, wherecanonicalize= JSON with object keys sorted recursively (UTF-16 order), no whitespace, UTF-8. - View integrity: the ergonomic English
atoms/purposeare exactly what the sealedcanonical.contentprojects to (viewConsistent) — a tampered convenience view can't ride on a valid hash.canonical.contentis the source of truth. - Signatures: every
seal.signatures[].signatureHexis a valid Ed25519 signature by that signer'spublicKeyHexover the UTF-8 bytes of theseal.contentHashhex string. - Quorum: at least 2 valid signatures including at least one sovereign (
quorum.meets).
All run entirely in your process against the response — the recipe is also echoed in norm.canonical.recipe.
Errors
- Nothing sealed for
(id, date)→{ status: "not_found" }(a normal outcome). - Bad key, bad input, or server error → throws
GrundnormError(.status,.code).
Demonstrator note: the demo corpus (GDPR sample) is signed by demo keys, not institutions, and its accuracy is not yet jurist-graded. See the project's
DEMO-TRUTHFULNESS.md.
