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

@openparachute/scope-guard

v0.2.1

Published

Hub-issued JWT validation for Parachute resource servers (vault, scribe, parachute-agent, third-party modules).

Readme

@openparachute/scope-guard

Hub-issued JWT validation for Parachute resource servers (vault, scribe, parachute-agent, third-party modules).

The Parachute hub mints OAuth access tokens as RS256 JWTs and publishes its public keys at /.well-known/jwks.json. This library is the consumer-side mirror: every resource server uses the same verifier so the trust kernel doesn't drift between modules.

What's in the box

  • createScopeGuard({ hubOrigin, jwks?, jwksGetter? }) — factory bound to a hub origin. Holds the JWKS getter so the cache lives across requests. hubOrigin may be a string or a resolver function (for layered env-var precedence).
  • guard.validateHubJwt(token, { expectedAudience? }) — JWKS-backed verify. Pins iss to the configured hub origin, strict-checks aud (RFC 7519 string-or-array) when supplied. Throws HubJwtError (with a code) on failure.
  • parseScopes(raw) / extractBearer(authHeader) / looksLikeJwt(token) — string helpers every consumer reaches for.
  • hasScope(granted, required) — generic <resource>:<verb> and <resource>:<name>:<verb> matcher with admin ⊇ write ⊇ read inheritance. The lib is the engine, not the dictionary; per-service vocabularies and cross-resource catch-alls stay in each service.
  • HubJwtError.code — single error class with a coarse code: signature | issuer | expired | kid | jwks | audience | shape. Branch on code rather than catching subclasses.

Quick start

import { createScopeGuard, extractBearer, hasScope } from "@openparachute/scope-guard";

const guard = createScopeGuard({
  hubOrigin: () => process.env.PARACHUTE_HUB_ORIGIN ?? "http://127.0.0.1:1939",
});

async function enforceAuth(req: Request, vaultName: string) {
  const token = extractBearer(req.headers.get("authorization"));
  if (!token) return new Response("missing bearer token", { status: 401 });

  try {
    const claims = await guard.validateHubJwt(token, {
      expectedAudience: `vault.${vaultName}`,
    });
    if (!hasScope(claims.scopes, `vault:${vaultName}:read`)) {
      return new Response("insufficient scope", { status: 403 });
    }
    return { ok: true as const, claims };
  } catch (err) {
    return new Response(`invalid token (${(err as { code?: string }).code ?? "unknown"})`, {
      status: 401,
    });
  }
}

Design

See parachute-hub/docs/design/2026-04-29-scope-guard-library.md for full rationale, alternatives considered, and the migration sequence (vault → scribe → parachute-agent).

The lib lives as a sub-package of parachute-hub because the hub owns the JWT-issuance side and the scope vocabulary. It's published independently to npm as @openparachute/scope-guard.

Versioning

Pre-1.0 (0.x.y) — this is a young library:

  • Patches (0.1.00.1.1) are additive and behavior-preserving. Adopters can take patch bumps without review.
  • Minors (0.1.x0.2.0) may break adopters. Read the CHANGELOG before bumping.
  • -rc.N prereleases match the broader Parachute ecosystem's pre-1.0 governance — landed on the rc dist-tag on every code-touching PR; promotion to @latest is a deliberate npm dist-tag step.

The library's RC cadence is independent of @openparachute/hub's — they're shipped from the same repo but aren't coupled in version. A hub release doesn't imply a scope-guard release and vice versa.

Post-1.0 the library will follow standard semver — minors backward-compatible, majors with a migration note.

License

AGPL-3.0