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

@agecheck/node

v0.2.0

Published

AgeCheck Node SDK for gate policy, JWT verification, and signed verification cookies.

Readme

AgeCheck Node SDK (@agecheck/node)

CI Compatibility npm

TypeScript server SDK for age verification, designed to help websites implement compliant age-assurance flows across jurisdictions.

What this package is for

  • enforce gate policy server-side
  • verify AgeCheck credentials (did:web:agecheck.me and optional demo issuer)
  • issue and validate signed HttpOnly verification cookies
  • support Existing Gate Integration and multi-provider coexistence

Install

pnpm add @agecheck/node

Supported integration modes

  1. Managed gate mode: use AgeCheck gate route + verify route + signed cookie.
  2. Existing Gate Integration: keep your existing gate and add AgeCheck as one provider option.
  3. Hybrid mode: use AgeCheck gate while also supporting other providers in Provider Mode.

All modes converge into one normalized provider assertion and one signed cookie pipeline.

Minimal managed-gate integration

import { AgeCheckSdk } from "@agecheck/node";

const sdk = new AgeCheckSdk({
  deploymentMode: "production", // "demo" for demo deployments
  verify: {
    requiredAge: 18,
    allowCustomIssuer: false,
  },
  gate: {
    headerName: "X-Age-Gate",
    requiredValue: "true",
  },
  cookie: {
    secret: process.env.AGECHECK_COOKIE_SECRET!,
    cookieName: "agecheck_verified",
    ttlSeconds: 86400, // hostmaster-controlled (e.g. 31536000 for 1 year)
  },
});

export async function enforce(request: Request): Promise<Response | null> {
  return sdk.requireVerifiedOrRedirect(request, { gatePath: "/ageverify" });
}

export async function verifyEndpoint(request: Request): Promise<Response> {
  const body = (await request.json()) as {
    jwt?: string;
    payload?: { agegateway_session?: string };
    redirect?: string;
  };

  const result = await sdk.verifyToken(body.jwt ?? "", body.payload?.agegateway_session ?? "");
  if (!result.ok) {
    return Response.json(
      { verified: false, error: "Age validation failed.", code: result.code },
      { status: 401 },
    );
  }

  const setCookie = await sdk.buildSetCookieFromAssertion({
    provider: "agecheck",
    verified: true,
    level: result.ageTier,
    verifiedAtUnix: Math.floor(Date.now() / 1000),
    assurance: "passkey",
  });

  const headers = new Headers({ "content-type": "application/json" });
  headers.append("set-cookie", setCookie);

  return new Response(
    JSON.stringify({ verified: true, redirect: body.redirect ?? "/" }),
    { status: 200, headers },
  );
}

Existing Gate Integration (Provider Mode)

Use these helpers when a hostmaster already has a gate flow and wants to add AgeCheck as a provider:

import {
  AgeCheckSdk,
  buildSetCookieFromProviderAssertion,
  normalizeExternalProviderAssertion,
  verifyAgeCheckCredential,
  type ProviderVerificationResult,
} from "@agecheck/node";

const sdk = new AgeCheckSdk({
  deploymentMode: "production",
  verify: { requiredAge: 18 },
  cookie: { secret: process.env.AGECHECK_COOKIE_SECRET! },
});

export async function verifyProviderEndpoint(body: {
  provider?: string;
  jwt?: string;
  payload?: { agegateway_session?: string };
  redirect?: string;
}): Promise<Response> {
  const expectedSession = body.payload?.agegateway_session;
  if (typeof expectedSession !== "string" || expectedSession.length === 0) {
    return Response.json({ verified: false, code: "invalid_input", error: "Missing session." }, { status: 400 });
  }

  let assertion: ProviderVerificationResult;
  if ((body.provider ?? "agecheck") === "agecheck") {
    assertion = await verifyAgeCheckCredential(sdk, {
      jwt: body.jwt ?? "",
      expectedSession,
      assurance: "passkey",
    });
  } else {
    const externalResult: ProviderVerificationResult = await verifyOtherProvider(body);
    assertion = normalizeExternalProviderAssertion(externalResult, expectedSession);
  }

  if (!assertion.verified) {
    return Response.json(
      { verified: false, code: assertion.code, error: assertion.message, detail: assertion.detail },
      { status: 401 },
    );
  }

  const setCookie = await buildSetCookieFromProviderAssertion(sdk, assertion);
  return new Response(JSON.stringify({ verified: true, redirect: body.redirect ?? "/" }), {
    status: 200,
    headers: { "content-type": "application/json", "set-cookie": setCookie },
  });
}

Deployment modes

  • production
    • accepts production issuer credentials
    • gate is raised only when policy header requires it
  • demo
    • accepts demo + production issuer credentials
    • gate is always raised

Provider assertion contract

Provider results normalize to this shape:

{
  provider: string;
  verified: true;
  level: "18+" | "21+" | `${number}+`;
  session: string; // UUID
  verifiedAtUnix: number;
  assurance?: string;
  verificationType?: "passkey" | "oid4vp" | "other";
  evidenceType?: "webauthn_assertion" | "sd_jwt" | "zk_attestation" | "other";
  providerTransactionId?: string;
  loa?: string;
}

This keeps provider internals isolated while preserving one site-level cookie and enforcement model. payload.agegateway_session and provider assertion session are treated as required UUID values.

Framework adapters

@agecheck/node includes framework adapter helpers:

  • createExpressGateMiddleware, createExpressVerifyHandler
  • createFastifyGateHook, createFastifyVerifyHandler
  • createHonoGateMiddleware, createHonoVerifyHandler
  • createNuxtGateMiddleware, createNuxtVerifyHandler

See /docs/ADAPTERS.md for adapter mapping and behavior notes.

Worker reference

worker-demo/ is a reference backend implementation (verify endpoint + gate page + cookie endpoints). It is useful for validation and demos, but production adopters should wire the SDK into their own server routes/middleware.

Existing sites

See /docs/EXISTING_SITES.md for the migration pattern that keeps your existing templates/content and moves enforcement into middleware.

Full hostmaster guide

See /docs/HOSTMASTER_E2E.md for the full request lifecycle and production enforcement model.

Framework compatibility

See /docs/COMPATIBILITY.md for latest-framework compatibility coverage and CI validation scope.

Versioning and releases

See /docs/VERSIONING.md.

Quality gates

pnpm typecheck
pnpm test
pnpm build

License

Apache-2.0