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

tr-jwt-chain

v1.0.0

Published

Immutable JSON audit chain with cryptographically chained JWT

Readme

tr-jwt-chain

Immutable audit-chain helper built on cryptographically linked JWT records.

Each record is a signed compact JWT whose header contains the signature of the previous record as parent. The package can append records, resume from a previous head, and replay or validate an existing chain.

Reference

Installation

npm install tr-jwt-chain

Node.js >=24.0.0 is required.

Export

const JwtChain = require('tr-jwt-chain');

Constructor

const chain = new JwtChain({
  alg: 'HS256',
  key: 'secret',
  kid: 'chain-key-1',
  head: null,
  omitSeqNo: false
});

Configuration fields:

  • alg: required JWT signing algorithm
  • key: signing or verification key
  • kid: required for non-empty HMAC keys and all asymmetric modes
  • head: optional previously issued token used to resume the chain
  • omitSeqNo: optional boolean (default false). When true, the chain does not emit a seqno field in the token header. When resuming from a head token, the sequencing mode is taken from that token's header — if omitSeqNo is also given explicitly and disagrees with what the head carries, the constructor throws.

Supported algorithms:

  • HS256, HS384, HS512
  • ES256, ES384, ES512
  • RS256, RS384, RS512
  • ML-DSA-44, ML-DSA-65, ML-DSA-87

Key handling:

  • HMAC mode accepts a raw string, Buffer, typed array, or oct JWK
  • asymmetric mode accepts PEM, KeyObject, or JWK
  • asymmetric mode becomes replay-only when only a public key is provided

initialize(extraProperties)

Creates the first chain record.

The payload starts with:

  • random id
  • alg
  • optional kid
  • optional public key JWK for asymmetric chains

Any extraProperties are merged into that initial payload.

record(data)

Appends a new record and returns the compact JWT string.

  • data must be a JSON object
  • the token header includes typ, alg, kid, optional parent, and (unless omitSeqNo is set) seqno
  • parent is set to the previous record signature
  • seqno starts at 0 for the initialise token and increments by one for every subsequent record

replay(token)

Validates a token against the current chain state and advances the internal head.

Replay enforces both parent linkage and — when the chain is in sequence-numbering mode — that the token's seqno is exactly previous_seqno + 1. A chain with omitSeqNo: true rejects any token that carries a seqno; a chain with omitSeqNo: false (default) rejects tokens that omit it.

check(token)

Validates a token without advancing the internal head.

Use this for detached verification of a single record. check validates the signature, typ, alg, and kid, but does not enforce parent or seqno linkage — those checks belong to replay.

head()

Returns the current head signature.

Example

const JwtChain = require('tr-jwt-chain');

const chain = new JwtChain({
  alg: 'HS256',
  key: 'kukkuureset',
  kid: 'hmac1'
});

const first = chain.initialize({ system: 'orders' });
const second = chain.record({ action: 'create', id: 1 });

const replay = new JwtChain({ alg: 'HS256', key: 'kukkuureset', kid: 'hmac1' });
console.log(replay.replay(first));
console.log(replay.replay(second));

CLI tool — jwt-chain-tool

A small command-line driver is bundled for inspecting chain files produced by this library. Install globally (npm i -g tr-jwt-chain) to get the jwt-chain-tool binary on $PATH, or invoke it through npx tr-jwt-chain jwt-chain-tool ... from within a project that has tr-jwt-chain as a dependency.

jwt-chain-tool <command> [options] <chain-file> [target]

Commands:

  • verify <chain-file> — replay the whole chain and exit 0 if every token verifies, every parent linkage holds, and (for seqno-enabled chains) every seqno is exactly previous + 1. Reports Chain integrity verified. Chain length is N events. on success; exits non-zero with the offending line number on the first failure.
  • extract <chain-file> — replay the chain and print every event payload, one JSON object per line.
  • extract <chain-file> <seqno> — replay until the token whose header carries that seqno, print the payload, and stop. The chain is not walked past the matched token. Exits non-zero if no such event exists, or if the chain is in omitSeqNo mode.
  • extract <chain-file> <event-id> — same, but matching by the third (signature) segment of the chain JWT. Use when sequence numbers are absent or unavailable.

A target made up entirely of digits is interpreted as a seqno; otherwise it is taken as an event id. Pass --help for the full syntax.

Options:

  • --event-chain-key=<jwk-file> — verification key for the chain. Accepts the public half of an asymmetric chain key or, for HMAC chains, the symmetric oct JWK. For asymmetric chains, the key's public part is checked against the public JWK embedded in the chain's root event; a mismatch aborts the run. For HMAC chains the option is required, since the symmetric key is not embedded. When omitted, the embedded public key from the root event is used.
  • -v, --verbose — extra output. For verify: print alg, key id, key type, sequencing mode, and the root event id. For extract: prefix each emitted payload with # seqno=<n> id=<chain-id>.
  • -p, --pretty — pretty-print emitted JSON (JSON.stringify(payload, null, 2)).

Exit codes: 0 on success, 1 on chain integrity failure / target not found / bad key, 2 on argument errors.

Notes

  • Tokens are compact JWT strings, but the payload semantics are chain-specific.
  • Replay will fail if token metadata, signature, or parent linkage does not match.
  • A chain resumed with head continues from the referenced token signature.

Author

Timo J. Rinne [email protected] — https://github.com/rinne/

Copyright

Copyright © 2023–2026 Timo J. Rinne [email protected]. See COPYING for the full MIT license text.

License

MIT License