npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zanii/credentials

v0.1.0

Published

Verifiable institutional credentials — diplomas, licences, certifications — offline-verifiable in milliseconds with no call to the registrar. Four checks: signature, expiry, revocation (with an explicit freshness window), and a domain-bound issuer root-of

Readme

@zanii/credentials

Verifiable institutional credentials — diplomas, professional licences, halal/organic certifications, pilot ratings. Verify one offline, in milliseconds, with no phone call to the registrar.

A credential is the sentence Zanii already signs for agents: "Issuer I attests that holder H holds claim C, until date E, revocably."

The package is not the credential — it is the root of trust

A signature only proves a key signed this. It does not prove the key is the University of Dubai. So verification runs four checks, and the fourth is the one that matters:

  1. the issuer's signature is valid,
  2. the credential has not expired,
  3. it is not revoked — against a signed list with an explicit freshness window,
  4. the issuer DID resolves to a named institution — bound to a domain the institution controls, at https://<domain>/.well-known/zanii-issuer.json.

Domain-binding deliberately reuses the web's existing trust anchor (the same one TLS and .well-known OIDC rely on) rather than inventing a new one.

Zanii is not an accreditation authority and must never become one. We verify that whoever controls uod.ac.ae published this DID. We do not decide who is a real university. Becoming the accreditor would make us a political chokepoint, a liability sink, and exactly the dependency institutions cannot afford.

npm install @zanii/credentials @zanii/core

Issue (the institution)

import { buildCredential, buildRevocationList } from '@zanii/credentials';

const cred = buildCredential({
  issuer: uni.did, issuerDomain: 'uod.ac.ae', holder: graduate.did,
  scope: 'degree.bachelor.cs', claim: { title: 'BSc Computer Science', grade: 'First' },
  issuedAt, exp: '2099-01-01T00:00:00Z',
}, uni.privateKey);

// publish periodically; the window is the freshness bound verifiers rely on
const list = buildRevocationList({ issuer: uni.did, revoked: [revokedHash], issuedAt, validUntil }, uni.privateKey);

The institution serves, at https://uod.ac.ae/.well-known/zanii-issuer.json:

{ "v": 1, "name": "University of Dubai", "domain": "uod.ac.ae", "dids": ["did:key:z..."] }

(Key rotation: list the new DID alongside the old during the overlap window.)

Verify (the employer, bank, border officer — anyone, free, offline)

import { verifyCredential, resolveIssuer, verifyPresentation, buildPresentation } from '@zanii/credentials';

const r = await verifyCredential(cred, { resolver: resolveIssuer, revocationList: list });
r.ok;                    // all four checks passed
r.issuer.name;           // "University of Dubai" — the institution, not just a key
r.revocationFreshness;   // 'fresh' | 'stale' | null  ← never assumed

// A credential is NOT a bearer token — make the holder prove possession:
const challenge = crypto.randomUUID();
const p = buildPresentation({ credential: cred, challenge, ts }, holder.privateKey);
verifyPresentation(p, cred, challenge);   // a thief with the FILE but not the KEY fails

Nothing is silently assumed. Omit the resolver and verifyCredential tells you institutional identity was not verified. Omit the revocation list and it tells you revocation was not checked. ok is never true on an unchecked assumption.

Honest limits (read these)

  • We verify institutional identity, never the truth of the claim. A corrupt university can sign a fake degree — but it does so with its own key, on an anchored record. The fraud becomes attributable and permanent instead of deniable. That is the product; it is not "we make lying impossible."
  • The domain is the trust root. Whoever controls uod.ac.ae controls the credential. A compromised domain compromises everything issued under it. Harden with DNSSEC, rotate keys with an overlap window, and consider an independent co-signer (@zanii/witness).
  • Offline revocation is a snapshot. A credential verified offline is verified as of the list you hold. The list carries valid_until, and a stale list is reported as stale — the freshness bound is stated, never assumed. High-assurance verifiers should reach the log.
  • W3C Verifiable Credentials export is not v1 — our credentials are conceptually VC-shaped and an export adapter is an obvious later bridge. Deliberately out of scope here.

Changelog

  • 0.1.0 — initial release: buildCredential, verifyCredential (four checks), resolveIssuer (domain-bound root of trust), buildRevocationList (explicit freshness window), buildPresentation/verifyPresentation (possession, not bearer).

License

Apache-2.0.