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

cursedauth

v0.9.3

Published

The app side of fleet SSO — sign in through the accounts service, keep a local snapshot of who signed in, and gate the app on it. Bun + Hono + React, one SQLite file per app.

Readme

cursedauth

The app side of "sign in through the accounts service". Mount it in a Bun + Hono app and the app has sessions, multi-account switching, an account menu, and a gate — without a password surface of its own.

import { createSsoConsumer, createUserSessionStore, mountGatedApp } from "cursedauth";

const sessions = createUserSessionStore({
  cookieName: "flix_session",
  dbPath: `${dataDir}/sessions.sqlite`,
  sessionSecret,
  sessionTtlSeconds: 60 * 60 * 24 * 30,
});
const sso = createSsoConsumer({
  app: "flix",
  authUrl: "https://auth.example.com",
  publicUrl: "https://flix.example.com",
  registeredAudiences: ["flix", "flix-local"],
  sessions,
  db,
});
mountGatedApp(app, { gate: sso, mountPublic: (a) => sso.mountSsoRoutes(a), mount: routes });

What it is not

It is the consumer, never the provider. It holds no password, mints no grant, and has no user table beyond a local snapshot of whoever has signed in here — so request-time auth never calls out, and the accounts service being down breaks new logins and nothing else. The provider is a separate service reached over HTTPS at authUrl; this package's only knowledge of it is that URL and its public key.

Subpaths

| import | side | what | |---|---|---| | cursedauth | server | the barrel: consumer, sessions, gate, census | | cursedauth/sso-consumer | server | the six routes and requireUser | | cursedauth/user-sessions | server | signed cookies + a sessions table, per app — the bun:sqlite half | | cursedauth/user-sessions-core | server | the same store over a SessionRows seam, plus SESSIONS_DDL. Worker-safe | | cursedauth/sso-user-store | server | the sso_users snapshot behind SsoUserStore, plus SSO_USERS_DDL. Worker-safe | | cursedauth/d1-stores | server | both seams on Cloudflare D1: one snapshot per invocation, writes settled before the response. Worker-only | | cursedauth/mount-gated | server | mount public routes before the gate, gated ones after | | cursedauth/content-census | server | answer "what has this account made here?" by COUNT | | cursedauth/account-slots | both | several accounts signed in on one browser | | cursedauth/sso | both | the grant: its wire shape, its claims, its verification | | cursedauth/session-claims | server | the bearer-token half: SESSION_CLAIMS_KEY, SessionClaims, createRequireSession. Worker-safe — reaches no bun:sqlite | | cursedauth/constant-time | both | constantTimeEqual — compare two secrets without leaking where they differ | | cursedauth/secure-request | both | isSecureRequest — whether a request arrived over HTTPS (reading x-forwarded-proto behind the tunnel), the one question the cookie Secure attribute turns on. Published 0.9.3 because patterns and auth each carried a copy (task 2106) | | cursedauth/offline-grant | both | the bounded offline window: how long a device with no network may keep using cached content | | cursedauth/auth | browser | startSsoSignIn, useSsoAutoSignIn, session hooks | | cursedauth/account-ui | browser | the account menu | | cursedauth/account-slot-client | browser | slot switching in the page | | cursedauth/testing | server | the grant→callback→cookie harness, for a consumer's own suite |

🔴 The barrel reaches bun:sqlite. A browser bundle imports the three browser subpaths and never the root — and so does a Cloudflare Worker, which is why cursedauth/session-claims exists. apps/patterns could not wrangler deploy at all on 2026-09-18 (Could not resolve "bun:sqlite", naming dist/userSessions.js) because one string constant was reachable only through the barrel. Which subpaths may reach bun:sqlite is now a CHECK — src/subpathsReachNoBunBuiltin.test.ts — and that allowlist may only shrink.

🔴 Two different things are called a "grant" here, and only one is a credential. cursedauth/sso has the grant: signed by the accounts service, single-use, and it authorizes a sign-in. cursedauth/offline-grant has an OfflineGrant: a local stamp saying "this device completed a verified session for account X at time T", which authorizes nothing, is never sent anywhere, and only bounds how long already-cached bytes may be replayed while there is no network to re-check. Separate subpaths, no import between them.

🔴 This table is a CHECK, not prosesrc/publishShape.test.ts fails if an export subpath is missing a row. A subpath nobody can find is a subpath every app re-implements: constant-time shipped on 2026-09-17 after three apps had each copied constantTime.ts into their own src/, because it was on no subpath at all. Add the exports entry and the row in the same commit.

Where it came from, and what was cut

Extracted 2026-09-14 from the previous generation's satellite-kit, which was the whole application platform — build, vite, dev-runner, smokes, backups, launchd agents, route manifests, metrics, mail — with identity inside it. Only identity came here.

Measured before the cut. Seeding the closure from the subpaths apps import and following relative imports:

| seeded from | files | what pulled the tail in | |---|---|---| | the 8 subpaths including the root barrel | 65 | the root IS the whole satellite server: metrics, engagement, mail, binary store | | the 7 identity subpaths only | 25 | — | | what this package ships | 21 | see the three cuts below |

@aws-sdk/client-ses was the dependency the extraction was told to prune. It never had to be pruned: it enters through mailer.ts, which is reachable only from the root satellite-server barrel, not from sso-consumer or user-sessions. This package's external surface is hono, react, react-dom, bun:sqlite and node builtins — nothing else, and no runtime dependencies block at all.

Three things were deliberately left behind:

  • fleet/registry.ts + fleet/directory.ts (936 lines) — a fleet-wide table of every app compiled into the shared library, and the /api/fleet/directory route that served it. Every app carried a roster of every other app, so adding one meant editing the platform. The one thing the consumer genuinely needed from it is now SsoConsumerOptions.registeredAudiences: an app declares its own doors.
  • ipGeo.ts — a machine-wide 375 MB IP→city snapshot, defaulted-on, living outside any repo. placeLookup is still injectable; unset, a session row records the city the edge headers already carry.
  • ownerAuth.server.ts — single-principal password auth (argon2, one owner). Nothing here signs in that way, and keeping it would have made cursedbelt a runtime dependency of an auth library for one re-exported type. The SSO path used exactly one function from it; that is src/secureRequest.ts, with its own suite.