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

@flashyos/checkpoint

v0.2.0

Published

checkpoint/1 — a Merkle tree head over the sealed claims an organisation already publishes. RFC 6962 hashing, inclusion and consistency proofs, verifiable offline against the fragments themselves.

Readme

@flashyos/checkpoint

A Merkle tree head over the sealed claims you already publish. RFC 6962 hashing, inclusion and consistency proofs, verifiable offline against the fragments themselves.

npx @flashyos/checkpoint head --origin repo/your-repo

No server. No collector. No account. A checkpoint.json beside the fragments it commits to, which anybody can recompute.


Read this first

A tree head is easy to over-read, so here is the honest boundary.

It proves that the fragments you published are the fragments the root describes. Recompute and compare. That catches a record edited after the fact, an emitter that silently dropped entries, a served copy that has drifted from its source, and two parties who think they hold the same record and do not.

It does not prove that history was never rewritten. You compute the root, you publish the root, and you hold the data — so you could recompute and republish after changing anything. That gap closes with consistency proofs between retained heads and cosigning by a witness who is not you, and neither is in version 1.

So heads here are unsigned, deliberately. A signature over a root you computed, checked with a key you published, is ceremony without a property. The field exists in the schema and stays empty until there is a witness for it to mean something to.


What goes in the tree

Assertions, not activity — statements someone might later dispute:

  • shipped/1 entries — what shipped
  • directory nodes, edges and assertions — what you say about yourself (unsealed today, so they contribute nothing yet)

Not commits, not deploys, not page rebuilds. Those are churn, and nobody will ever challenge a footer clock.

Not backlog/1 either, and that is structural. An item decays and is never sealed, so there is no digest to commit to — a tree can only cover the past tense. Even sealed, an intention is supposed to change, and a root that went stale whenever somebody restated a plan would teach readers to ignore it.

A shipped/1 entry already carries a sha256 seal, so this package hashes nothing new at the claim level — it commits to seals you have.

A record missing an id or a digest is skipped, not hashed. A tree that exists to prove sealing must not contain something unsealed.


Using it

import { claimsOf, headOf, proofFor, checkProof } from '@flashyos/checkpoint'

const claims = claimsOf([shiplogFragment, directoryFragment])
const head = headOf('repo/acme', claims)
// { checkpoint: '1', origin: 'repo/acme', size: 97, root: '9f2b…', at: '…' }

const proof = proofFor('repo/acme', claims, 'ship/acme/a1b2c3')
checkProof(proof, head) // true

checkProof takes the head separately, on purpose. A proof carries its own root for convenience; checking it against that root is circular. Pass the head you already trust.

Did my published head drift?

import { headMatches } from '@flashyos/checkpoint'
headMatches(publishedHead, [shiplogFragment, directoryFragment]) // false if either changed

The estate tier

An estate/<slug> head is a tree whose leaves are other heads' roots — so the hub holds hashes and no data, and a property can still prove its own record with the hub absent entirely.

import { estateHead, memberProof, verifyThroughEstate } from '@flashyos/checkpoint'

const estate = estateHead('estate/flashy', [
  { origin: 'repo/alpha', root: alphaHead.root, size: alphaHead.size },
  { origin: 'repo/beta',  root: betaHead.root,  size: betaHead.size  },
])

// One claim, verified to the estate root through both tiers.
verifyThroughEstate(
  proofFor('repo/beta', betaClaims, 'ship/beta/xyz'),
  memberProof(estate, 'repo/beta'),
  estate.root,
)

Properties that could not be read are listed in unreachable[] rather than dropped — a root over nine of ten properties is a different root, and a reader must see which nine.


Without a toolchain

vendor-checkpoint.mjs imports nothing but node: builtins. Copy it in and run it:

node vendor-checkpoint.mjs emit                    # write checkpoint.json
node vendor-checkpoint.mjs verify                  # recompute, and prove every leaf
node vendor-checkpoint.mjs prove ship/acme/a1b2c3  # an inclusion proof
// .checkpoint/config.json
{
  "origin": "repo/your-repo",
  "fragments": ["shiplog.fragment.json", "directory.fragment.json"],
  "serve": "public/.well-known/checkpoint.json"
}

A fragment you declared and it cannot find is named in the output, never skipped quietly — a head over two fragments when three were declared is a different root, and silence would make it look complete.

The vendored emitter and this package are held to the same roots by a drift test that runs both and compares, across thirteen tree sizes. Two Merkle implementations that disagree by one byte produce completely different roots, and each one calls the other's head forged.


The tree

RFC 6962 §2.1, unchanged — not a variant. Certificate Transparency has had a decade of adversarial review on exactly this structure.

MTH({})   = SHA256()
MTH({d0}) = SHA256(0x00 || d0)
MTH(D[n]) = SHA256(0x01 || MTH(D[0:k]) || MTH(D[k:n]))    k = largest power of 2 < n

The 0x00 / 0x01 prefixes are the whole security argument. Without them a leaf whose data is two concatenated hashes is indistinguishable from the interior node over them, and an attacker can present an interior node as a leaf to prove the inclusion of something never added.

Claims are sorted by id so the root is a pure function of the claims — two people with the same fragments must get the same tree.

SPEC.md has the format in full, including why size is not independent evidence and what version 2 owes.


Licence

Apache-2.0.