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

@wtfalch/keys

v0.3.0

Published

The estate's own bearer keys, issued to callers and held on their behalf: two entries, issued and held, nothing stored in common.

Readme

@wtfalch/keys

@wtfalch/keys issues the estate's own bearer keys to callers and holds keys other parties issued to the estate, injecting held keys into a running service at request time and into a build at build time. It owns no authentication or authorisation of its own — every check runs through @wtfalch/auth and @wtfalch/authz.

Install

pnpm add @wtfalch/keys drizzle-orm@^0.45.2

Dev

pnpm build
pnpm typecheck
pnpm test

Security upgrade

Apply the additive 0004_keys_security.sql migration in every consumer database before relying on the updated guards. All issuer processes must upgrade together for issuance/cascade serialization. See the remediation and rollout notes.

New bearer secrets have a 32-character base32 tail (160 random bits). Existing 20-character tails remain accepted. Rotation refuses invalid stored signatures and returns conflict if the row changes during signing.

Held keys use active cache expiry (60 seconds by default) and retain at most 256 versions per instance. Set cacheSeconds: 0 or maxCacheEntries: 0 to disable caching. Call dispose() to zero cached keys, clear timers and refuse further operations. A local forget/revocation invalidates pending opens; other processes remain bounded by their own cache TTL. Plaintext callbacks can copy or return values, so their lifetime cannot be enforced by the SDK.

Issued-key environments

Every issued credential carries a built-in environment, 'live' or 'test' (default 'live'), passed on issue() and reported by check() and lineageOf(). A credential can only mint a child in its own environment — issue() returns { ok: false, reason: 'environment_mismatch' } otherwise. Apply 0005_keys_environment.sql alongside 0004_keys_security.sql.

Issued-key usage tracking

Every successful check() stamps lastUsedAt and increments useCount on the credential's row — read them off KeysIssuedCredentialRow directly (an admin UI's own query, not a new check() return field). The write is best-effort: it never turns a genuine secret into a refusal, and a revoked, expired, tampered or wrong-secret check never bumps it. Apply 0006_keys_usage.sql alongside 0004_keys_security.sql and 0005_keys_environment.sql.

Per-issued-key rate limits

CreateCredentialIssuerOptions.rateLimiter (optional) is consulted on every check(), keyed by the credential's own id — spent on every attempt against a known credential, matched secret or not, so an unlimited number of wrong guesses can't get around it. Refused as { ok: false, reason: 'rate_limited', retryAfterMs }. createPostgresRateLimiter({ db, limitPerWindow, windowMs? }) is a ready-made fixed-window limiter backed by the host's own Postgres (0007_keys_rate_limit.sql, applied alongside 0004–0006); bring your own RateLimiter for anything else (Redis, D1, …). Omit it and check() behaves exactly as before this existed — this was previously only enforced on the host's own service credential (packages/worker/src/ratelimit.ts), never on an individual end-user issued key.

Outbound webhooks

@wtfalch/keys/webhooks's createWebhookDispatcher({ url, secret? }) returns a function that POSTs a lifecycle event as JSON — a drop-in for ./issued's audit option (credential.minted / .rotated / .revoked) or ./held's (key.used). With secret, the body is HMAC-SHA256-signed into an X-Keys-Signature header; the receiver checks it with verifyWebhookSignature(body, signature, secret). Delivery is fire-and-forget and best-effort — a subscriber outage never fails the call that produced the event, it only calls onDeliveryError.