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

@decartai/cf-access

v0.2.1

Published

Cloudflare Access middleware for Decart internal apps hosted on Vercel. Verifies the Cf-Access-Jwt-Assertion JWT and fails closed.

Downloads

654

Readme

@decartai/cf-access

Locks a Decart internal app (Next.js on Vercel) behind our Cloudflare Access front door. Add two lines to your app and only people signed in with a @decart.ai Google account can reach it.

Add it to your app

npm install @decartai/cf-access

Create proxy.ts at the root of your project (next to app/ — or inside src/ if your app uses a src directory):

export { proxy } from '@decartai/cf-access/next'

On Next.js 13.4–15, the file is middleware.ts and the export is middleware (same function — Next 16 renamed the convention):

export { middleware } from '@decartai/cf-access/next'

When upgrading an app to Next 16+, rename the file — a leftover middleware.ts will eventually be ignored by Next, silently reopening direct *.vercel.app access.

That's it for the code. To put the app on its internal address, follow the Exposing an internal app checklist below.

What you get

  • Every production request must carry a valid Cloudflare Access JWT — the cryptographic proof that the visitor signed in through https://<your-app>.decart.dev. Requests that sneak in through <project>.vercel.app or any other side door get a 401.
  • Fail closed: if Cloudflare isn't in front yet or something is misconfigured, the app is blocked, never silently public.
  • next dev works normally (no auth locally).
  • Vercel preview deployments work normally — they're protected by Vercel Authentication instead (see below), so PR previews don't need Cloudflare.
  • Your app learns who's signed in for free:
import { headers } from 'next/headers'
import { getAccessViewer } from '@decartai/cf-access'

const viewer = getAccessViewer(await headers())
// viewer?.email === '[email protected]'

The x-decart-user-email / x-decart-user-id request headers are set by the middleware after verification and can't be spoofed from outside (incoming values are stripped on every request the middleware sees). If your app defines its own config matcher, routes excluded from it never get that stripping — on those routes use verifyAccessViewer(await headers()) instead, which re-verifies the JWT cryptographically.

Exposing an internal app: the full checklist

  1. Vercel → your project → Settings → Domains: add <name>.decart.dev.
  2. Vercel → Settings → Deployment Protection: Vercel Authentication ON, scope Standard Protection (free — this is the team default for new projects; just confirm it's on).
  3. Cloudflare (decart.dev zone): add a proxied CNAME <name>cname.vercel-dns.com.
  4. Install this package + the two-line proxy.ts, deploy.
  5. Open https://<name>.decart.dev in a private window — you should get the Google login, then the app. Then try the project's *.vercel.app URL — you should get a 401 or a Vercel login, never the app.

Pick a name that isn't already used by a Twingate-internal service — check the reserved-names list in the internal docs before claiming a subdomain.

Things that need extra care

  • OAuth callbacks / absolute URLs: update them to https://<name>.decart.dev.
  • Inbound webhooks (Stripe, Slack, GitHub…): they can't pass Google SSO. Either give the route a publicPaths entry (below) and rely on the provider's own signature verification, or create a Cloudflare Access service token and send its headers with the webhook if the provider supports custom headers.
  • CI / cron / app-to-app calls: use a Cloudflare Access service token (Zero Trust → Access → Service Auth). Send CF-Access-Client-Id / CF-Access-Client-Secret headers with requests to the decart.dev address; Cloudflare exchanges them for a JWT and this middleware accepts it. The app sees the token's name in x-decart-service-token.

Customizing

// proxy.ts (or middleware.ts on Next ≤15, exported as `middleware`)
import { createAccessMiddleware } from '@decartai/cf-access/next'

export const proxy = createAccessMiddleware({
  // Routes served without Decart SSO. A string matches the path and any
  // subpath. Only do this for routes that verify the caller themselves
  // (e.g. webhook signature checks). '' and '/' are rejected at startup;
  // anchor your RegExps.
  publicPaths: ['/api/webhooks/stripe', /^\/healthz$/],

  // Set false if this project can't guarantee Vercel Deployment Protection
  // is enabled: preview deployments then also require the Access JWT.
  allowPreviews: true,
})

Next.js only honors a config matcher written literally in your own proxy.ts/middleware.ts. The default (no config) runs on every route, which is the safe choice. If you must exclude paths, prefer publicPaths over a matcher — excluded-by-matcher paths skip the identity headers too.

Environment variables

| Variable | Effect | | --- | --- | | CF_ACCESS_TEAM_DOMAIN | Override the baked-in team domain (slug or full domain). | | CF_ACCESS_AUD | Override the baked-in Access application AUD tag. | | DECART_ACCESS_DISABLED=1 | Skip all checks — for running a production build locally. Ignored on Vercel (any deployment with VERCEL/VERCEL_ENV set), so a copied .env can't unlock production. |

How it works

you ── https://name.decart.dev ──► Cloudflare edge
                                     │  Access: Google SSO (@decart.ai)
                                     │  adds Cf-Access-Jwt-Assertion (signed JWT)
                                     ▼
                                   Vercel ──► this middleware
                                                │  verifies JWT signature against
                                                │  the team's public JWKS + issuer + AUD
                                                ▼
                                              your app (+ x-decart-user-* headers)

Anyone hitting Vercel directly (the *.vercel.app URL, curl --resolve tricks, etc.) has no way to mint that JWT — only Cloudflare's private keys can sign it — so the middleware rejects the request. Verification happens in Edge Middleware with jose; the JWKS is fetched once per runtime and cached.

Environments:

| Environment | Behavior | | --- | --- | | next dev | Allowed (no auth). | | Vercel preview | Allowed by this middleware; gated by Vercel Authentication upstream (Vercel's check runs before middleware, so reaching the app already required Vercel SSO). | | Production | Valid Access JWT required on every host and route. |

Maintainers

  • DEFAULT_TEAM_DOMAIN and DEFAULT_AUD in src/constants.ts are the org's Zero Trust team slug and the wildcard *.decart.dev Access application's AUD tag. If that Access app is ever recreated, update DEFAULT_AUD and release. With an empty AUD the middleware fails closed with a 500 — nothing is ever silently open.
  • Release: npm run release — bumpp prompts for the version, commits, tags, and pushes. The v* tag triggers .github/workflows/release.yml, which publishes to npm via trusted publishing (GitHub OIDC — no npm token anywhere), then generates the GitHub release notes with changelogithub. prepublishOnly runs the typecheck, tests, and build. The package is public on purpose — it contains no secrets: verification uses Cloudflare's public keys, and the team domain is visible to anyone who hits the login redirect.
  • Rotating/renaming the Access app changes the AUD → bump DEFAULT_AUD and release; apps pick it up on their next dependency update, or immediately via the CF_ACCESS_AUD env var.