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

@torquedev/bundle-identity

v0.1.0

Published

Authentication, sessions, JWT lifecycle

Downloads

13

Readme

@torquedev/bundle-identity

Authentication, JWT sessions, and user management. Part of the Torque composable monolith framework.

Provides sign-up, sign-in, token refresh, and user introspection as a self-contained Torque bundle. Other bundles can call its interfaces to verify tokens and retrieve users without coupling to the underlying storage or cryptographic implementation.

Schema

| Table | Column | Type | Constraints | |-------|--------|------|-------------| | users | id | TEXT | Primary key, UUID | | users | email | TEXT | NOT NULL, unique | | users | password_digest | TEXT | NOT NULL | | users | name | TEXT | | | users | role | TEXT | NOT NULL, default 'user' | | refresh_tokens | id | TEXT | Primary key, UUID | | refresh_tokens | user_id | TEXT | NOT NULL, FK → users.id | | refresh_tokens | jti | TEXT | NOT NULL, unique — JWT ID for revocation | | refresh_tokens | expires_at | TEXT | NOT NULL — ISO 8601 timestamp |

Events

Published

| Event | Payload | Description | |-------|---------|-------------| | identity.user.authenticated | { userId, email, role } | Fired after a successful sign_in. | | identity.session.created | { userId, jti, expiresAt } | Fired when a new JWT access token and refresh token pair is issued (sign-in or refresh). | | identity.auth.failed | { email, reason } | Fired when authentication is attempted but fails (wrong password, unknown email, revoked token, etc.). |

Interfaces

| Interface | Arguments | Returns | Description | |-----------|-----------|---------|-------------| | getUser | { userId } | { id, email, name, role } | Retrieve a user by ID. Returns null if not found. | | validateToken | { token } | { valid, userId, role, jti } | Verify and decode a JWT access token. Returns { valid: false } on expiry, bad signature, or revoked JTI. | | revokeUserSessions | { userId } | { revoked: number } | Immediately invalidate all active refresh tokens for a user. Returns the count of tokens revoked. |

API Routes

| Method | Path | Auth | Description | |--------|------|------|-------------| | POST | /api/identity/sign_up | Public | Register a new user. Body: { email, password, name? }. Returns { user, accessToken, refreshToken }. | | POST | /api/identity/sign_in | Public | Authenticate with email + password. Returns { user, accessToken, refreshToken }. | | POST | /api/identity/refresh | Public (refresh token) | Exchange a valid refresh token for a new access token. Implements token rotation — the old refresh token is revoked and a new one is issued. | | GET | /api/identity/me | Required | Return the currently authenticated user. Reads identity from the authResolver-resolved user on req. |

Security

JWT Enforcement

  • The jwt_secret configuration key is required. Boot fails with a descriptive error if it is absent or empty.
  • Access tokens are signed with HMAC-SHA256. Tokens signed with a different algorithm are rejected.
  • Token expiry is enforced by the library; expired tokens return { valid: false } from validateToken rather than throwing.

Password Validation

Passwords are validated at sign-up with a minimum length of 8 characters. Shorter passwords are rejected with a 422 Unprocessable Entity response before any hashing occurs.

Constant-Time Authentication

Password comparison uses bcrypt (bcrypt.compare), which is constant-time by design. This prevents timing attacks that could be used to determine whether an email address is registered.

Token Revocation via JTI Blocklist

Every refresh token is issued with a unique JWT ID (jti). On refresh or explicit revocation:

  1. The old jti is deleted from the refresh_tokens table.
  2. validateToken checks the jti against the active token set; a missing or expired jti returns { valid: false }.

This means tokens can be revoked immediately without waiting for their natural expiry.

Session Limits

Each user may have at most 10 active refresh tokens at a time. When a new session is created and the limit would be exceeded, the oldest token (by expires_at) is automatically revoked to make room. This bounds the storage footprint and limits the blast radius of credential theft.

Intents

RevokeAccess Intent

The bundle exposes a RevokeAccess intent that can be triggered by AI agents or automation workflows to forcibly sign out a user:

| Property | Value | |----------|-------| | Intent name | RevokeAccess | | Trigger | identity.suspicious_activity or direct invocation | | Description | Revoke all active sessions for a given user ID | | Allowed tools | identity.revokeUserSessions | | Success criteria | All refresh tokens for the user are deleted; identity.session.revoked event published | | Human confirmation | Not required (automated security response) |

Dependencies

None. The bundle has no depends_on declarations and does not call any other bundle's interfaces.

Configuration

| Key | Required | Default | Description | |-----|----------|---------|-------------| | jwt_secret | Yes | — | Secret string used to sign and verify JWT access tokens. Must be kept confidential. | | jwt_ttl_seconds | No | 900 | Access token lifetime in seconds (default: 15 minutes). | | refresh_ttl_seconds | No | 2592000 | Refresh token lifetime in seconds (default: 30 days). |

Install

npm install @torquedev/bundle-identity

Or via git dependency:

npm install git+https://github.com/torque-framework/torque-bundle-identity.git

Usage

Reference this bundle in a mount plan:

bundles:
  identity:
    source: "git+https://github.com/torque-framework/torque-bundle-identity.git@main"
    config:
      jwt_secret: "${AUTH_SECRET}"
      jwt_ttl_seconds: 900
      refresh_ttl_seconds: 2592000

Other bundles that need to verify tokens or look up users declare the dependency:

# In another bundle's manifest.yml
depends_on:
  - identity

And call the interfaces via the coordinator:

const { valid, userId, role } = await coordinator.call('identity', 'validateToken', { token });
const user = await coordinator.call('identity', 'getUser', { userId });

License

MIT — see LICENSE