@uuaid/core
v0.2.1
Published
UUAID identifier grammar, canonical hashing, and crypto-agile signature envelopes.
Readme
@uuaid/core
Cryptographic primitives for UUAID — the identity + certification layer for AI agents ("the SSL/CA for agents").
- UUAID grammar — mint + parse
uuaid:<namespace>:<type>:<uuidv7>(durable, creation-time-ordered agent identifiers). - JCS canonicalization (RFC 8785) +
contentHash— stable, on-chain-ready content hashes for any JSON value. - Crypto-agile signature envelope — Ed25519 today,
ml-dsa-65(FIPS 204) for post-quantum. Hybrid = both signatures over one payload in one envelope. - Verifiable Badges (IAASO-0003) — seal, render to SVG, parse, and verify.
import { mintUuaid, contentHash, generateEd25519, sealEnvelope, verifyEnvelope } from "@uuaid/core";
const agent = mintUuaid("agent"); // { uuaid, uuid }
const signer = generateEd25519();
const env = sealEnvelope({ hello: "world" }, [{ key: signer, keyId: "k1" }]);
verifyEnvelope(env); // { valid: true, verified: 1, total: 1 }Verifying a badge
A badge carries its own signer's public key. Every structural check passes
for a badge anyone minted with a fresh keypair, so verification means nothing
until you pin the issuer against a known root. verifyBadge therefore fails
closed: no pin, no verdict.
import { parseBadgeSvg, verifyBadge } from "@uuaid/core";
// The registry's published roots. Fetch once and cache, or hard-code the pin.
const { keys } = await fetch("https://api.uuaid.org/.well-known/uuaid-registry.json").then(r => r.json());
const trustedIssuerKeys = Object.fromEntries(keys.map(k => [k.keyId, k.publicKey]));
const badge = parseBadgeSvg(await fs.readFile("badge.svg", "utf8"));
const r = verifyBadge(badge, { trustedIssuerKeys });
r.ok // true only when the issuer pinned AND the envelope is intact
r.level // "L1-trusted" | "L0-selfsigned" | "invalid" | …
r.pqProtected // a valid ML-DSA-65 signature is present
r.nameVerified // did the registry vouch for subject.displayName? usually false
r.checks // per-check detail; `severity: "warn"` entries are advisoryTwo things ok: true does not mean:
- It is not a name claim.
subject.displayNameandsubject.controllerare self-asserted by whoever registered the agent unlessnameVerifiedistrue. A signature says who issued the badge, never whose name is on it. - It is not a liveness check. The badge is a snapshot;
freshUntilbounds it. Re-check status against the registry (L3) for anything consequential.
Omitting trustedIssuerKeys returns ok: false, level: "L0-selfsigned". If
you genuinely want a structure-only inspection — a conformance probe, a badge
editor — pass allowUnpinnedIssuer: true and never treat the result as trust.
Built on the audited noble libraries. Node ≥ 18 and modern browsers. Apache-2.0 · uuaid.org
