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

@zamatica/auth-core

v0.1.0

Published

Pure-function cryptographic primitives for the zamatica fleet-env cert auth scheme. Ed25519 keys, RFC 8785 (JCS) canonicalization, certs, trust bundles, CRLs, HTTP request signing, and daemon-per-deploy identity. No framework dependencies.

Readme

@zamatica/auth-core

Pure-function cryptographic primitives for the zamatica fleet-env cert auth scheme.

This lib has zero framework dependencies — no NestJS, no Express, no DI. It's safe to consume from any TypeScript context (CLI, desktop main process, NestJS guards, browsers via Node-crypto-compatible polyfills). The NestJS wiring layer lives in @mtz/auth-backend (and will be harvested into @zamatica/auth-backend once a second downstream consumer exists).

What's in the box

| Module | What it does | |---|---| | errors | AuthError discriminated error type + Result<T, E> discriminated union | | roles | Centrally enumerated ROLE_NAMES + RoleName type + isRoleName() guard | | constant-time | constantTimeEqual() — wraps crypto.timingSafeEqual for signature comparisons | | jcs | RFC 8785 JSON Canonicalization Scheme — the ONLY canonicalizer used for signing | | serial | Deterministic cert serial from sha256(pubkey || issuedAt), first 16 bytes hex | | keypair | Ed25519 generate / sign / verify via node:crypto. Base64-of-DER representation. | | cert | Per-user cert sign / parse / verify | | trust-bundle | Per-fleet-env trust anchor (root(s) + CRL-signer subkey), with rotation support | | crl | Certificate revocation list sign / verify / serial-lookup | | http-signature | Sign and verify HTTP requests (method + canonical URL + ts + nonce + body hash + instance ID) | | daemon-identity | Per-deploy daemon keypair certification (TOFU pinning support) |

Crypto choices

  • Ed25519: small keys (32 bytes), fast, modern, no parameter choices to get wrong. Supported natively in Node 22+ via node:crypto.
  • SHA-256: for serials, body hashes, fingerprints. Sufficient for non-collision needs at these sizes.
  • AES-GCM: NOT in this lib — that's in @zamatica/auth-credentials for encrypted-file fallback storage.
  • No X.509: certs are JSON with a signature field; trust bundles are JSON with a signature field. Simple to read, simple to sign, no ASN.1 parser to misconfigure.

JCS — why it matters

Naive JSON.stringify produces non-deterministic bytes: key order is engine-dependent, numbers have multiple valid representations (1e2 vs 100 vs 100.0), whitespace is implementation-defined. Signing those bytes means a verifier with a different stringify produces a different digest, and signature verification silently fails.

RFC 8785 (JCS) pins exact rules: keys sorted lexicographically (by UTF-16 code units), numbers per ECMA-262, strings escaped per RFC 8259's shortest form. Every signature in this lib goes through canonicalize() first. Don't sign JSON.stringify(obj) — always sign canonicalize(obj).

Install

bun add @zamatica/auth-core
# or
npm install @zamatica/auth-core

Quick examples

Generate a keypair, sign + verify a payload

import { generateKeyPair, sign, verify } from '@zamatica/auth-core';

const { publicKey, privateKey } = generateKeyPair();
const payload = new TextEncoder().encode('hello');
const signature = sign(privateKey, payload);
const ok = verify(publicKey, payload, signature);  // true

Sign + verify a user cert

import { generateKeyPair, signCert, verifyCert, parseCert } from '@zamatica/auth-core';

const root = generateKeyPair();
const user = generateKeyPair();

const cert = signCert(
  {
    user: 'alice',
    acronym: 'mtz',
    fleetEnv: 'prod',
    pubkey: user.publicKey,
    issuedAt: new Date().toISOString(),
    expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
    roles: ['user', 'admin'],
  },
  root.privateKey,
);

const result = verifyCert(cert, root.publicKey);
if (!result.ok) {
  throw result.error;  // AuthError
}

Sign + verify an HTTP request

import { signRequest, verifyRequest } from '@zamatica/auth-core';

const headers = signRequest(cert, user.privateKey, {
  method: 'POST',
  url: new URL('https://daemon.example.com/api/foo?x=1'),
  body: new TextEncoder().encode('{"hello":"world"}'),
  timestamp: Math.floor(Date.now() / 1000),
  nonce: crypto.randomBytes(16).toString('hex'),
  instanceId: 'abc-123',  // optional but recommended; required for /admin/*
});

// On the daemon side:
const seenNonces = new Set<string>();
const verified = verifyRequest(
  {
    method: 'POST',
    url: new URL('https://daemon.example.com/api/foo?x=1'),
    body: new TextEncoder().encode('{"hello":"world"}'),
    headers: { /* ...the headers from above... */ },
    expectedInstanceId: 'abc-123',
    signatureWindowSeconds: 300,
    seenNonces: { has: (n) => seenNonces.has(n), add: (n) => seenNonces.add(n) },
  },
  trustBundle,
);
if (!verified.ok) {
  // verified.error.code is one of the AuthErrorCode values
}

Development

From the workspace root:

bunx nx build auth-core
bunx nx test auth-core