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

@michaelthielemann/kestrel-authn-multi

v5.8.1

Published

authn@1 with users and sessions stored via persistence@1; user management steps.

Readme

authn/multi

authn@1 with users and sessions in persistence@1 (authn_users, authn_sessions) – sessions survive restarts. Passwords are scrypt hashes; bootstrap creates the first user when the user collection is empty so a fresh install is not locked out. Identity claims: { username, roles }. Config: identifier (username | email – the credential field), minPasswordLength, sessionTtlSeconds, adminPermission, bootstrap { username, passwordHash, roles }.

The username is the identity – there is no e-mail field on a user. Roles are plain strings: the module never learns which ones a site defines, because authz@1 maps roles to permissions and answers questions about one identity only. What it can ask is whether a user still holds adminPermission (default users.manage), and it does so through the optional authz@1 dependency before every change that could remove the last one: deactivating, deleting or taking the permission away from the last active holder is LAST_ADMIN (409). Without an authz module nobody is known to be an admin and the guard stays silent.

Every step returns a Result; authn@1's own login/resolve/logout only ever answer Err(TRANSIENT) (wrong credentials are Ok(null)). createUser, setPassword, changePassword, setActive, updateUser, deleteUser, getUser, listUsers and cleanupSessions beyond the contract can additionally answer VALIDATION, CONFLICT, NOT_FOUND or LAST_ADMIN; a duplicate username is CONFLICT (409), the last admin guard is LAST_ADMIN (409).

| Step | reads | writes | errors | |---|---|---|---| | authn.login | – | token, identity, result | UNAUTHENTICATED, TRANSIENT | | authn.identifyUser | – | token?, identity? | TRANSIENT | | authn.requireUser | – | token, identity | UNAUTHENTICATED, TRANSIENT | | authn.loadIdentity | identity | result | UNAUTHENTICATED | | authn.logout | token | result | UNAUTHENTICATED, TRANSIENT | | authn.createUser | – | result | VALIDATION, CONFLICT, TRANSIENT | | authn.listUsers | – | result | TRANSIENT | | authn.getUser | params.id | result | NOT_FOUND, TRANSIENT | | authn.updateUser | params.id | result | VALIDATION, CONFLICT, NOT_FOUND, LAST_ADMIN, TRANSIENT | | authn.deleteUser | identity, params.id, payload.reassignTo | result | VALIDATION (self, bad target), NOT_FOUND, LAST_ADMIN, TRANSIENT | | authn.setPassword | params.id | result | VALIDATION, NOT_FOUND, TRANSIENT | | authn.changePassword | identity | result | VALIDATION, UNAUTHENTICATED, TRANSIENT | | authn.deactivateUser | params.id | result | VALIDATION (self), NOT_FOUND, LAST_ADMIN, TRANSIENT | | authn.activateUser | params.id | result | NOT_FOUND, TRANSIENT | | authn.cleanupSessions | – | result | TRANSIENT |

Deleting and the authored history. authn.deleteUser takes an optional reassignTo in the body: the id of an existing, active user who is not the one being deleted. An unknown id is 404, an inactive one, the deleted user themselves or a value that is not a string is 400 — and in each case the user stays. On success the step answers { ok: true, reassignTo: { id, name } | null }, name being the target's username at that moment. Emit the event with events.emit:user.deleted?with=result so the target travels in the payload, and let the pipelines behind that event decide what happens to what the user wrote: revisions.reassignAuthor moves or anonymises their revisions, audit.anonymize strips them from the audit log. The module itself deletes only the user row and their sessions; it knows nothing about revisions or audit entries.

Not included: self-service registration, password reset by mail, login rate limiting (pipeline concerns), an e-mail field.

Generated from the manifest

@michaelthielemann/kestrel-authn-multi – module authn/multi: provides authn@1; requires persistence@1; optional authz@1.

| Config | Type | Required | Default | |---|---|---|---| | identifier | enum | no | "username" | | minPasswordLength | integer | no | 12 | | sessionTtlSeconds | integer | no | 86400 | | adminPermission | string | no | "users.manage" | | bootstrap | object | no | – | | bootstrap.username | string | no | – | | bootstrap.passwordHash | string | no | (secret) | | bootstrap.roles | array | no | [] |

| Step | Summary | Reads | Writes | Input | Output | Errors | |---|---|---|---|---|---|---| | authn.login | Log in with credentials | – | token, identity, result | { username?: string, email?: string, password: string } | { token: string, identity: object, … } | 401 invalid credentials | | authn.identifyUser | Identify the caller if a valid token is present | – | token?, identity? | – | – | – | | authn.requireUser | Require a valid session | – | token, identity | – | – | 401 not authenticated | | authn.loadIdentity | Current identity | identity | result | – | { id: string, claims: object, … } | 401 not authenticated | | authn.logout | End the current session | token | result | – | { ok: boolean, … } | 401 not authenticated | | authn.createUser | Create a user | – | result | { username: string, password: string, roles?: string[] } | { id: string, username: string, roles: string[], active: boolean, createdAt: number, … } | 400 invalid input; 409 username already exists | | authn.listUsers | List users | – | result | – | object[] | – | | authn.getUser | One user | params.id | result | – | { id: string, username: string, roles: string[], active: boolean, createdAt: number, … } | 404 user not found | | authn.updateUser | Rename a user or set their roles (a role change ends their sessions) | params.id | result | { username?: string, roles?: string[] } | { id: string, username: string, roles: string[], active: boolean, createdAt: number, … } | 400 neither username nor roles given, or an empty one; 404 user not found; 409 username already exists (CONFLICT), or the last active admin would lose the admin permission (LAST_ADMIN) | | authn.deleteUser | Delete a user and their sessions for good; reassignTo names the active user their authored history moves to, without it the history is anonymised | identity, params.id, payload.reassignTo | result | { reassignTo?: string | null } | { ok: boolean, reassignTo: object | null, … } | 400 cannot delete yourself, or a reassignTo that is the deleted user, inactive or not a user id; 404 user not found, or reassignTo names no user; 409 the last active admin cannot be deleted (LAST_ADMIN) | | authn.setPassword | Set a user's password (ends their sessions) | params.id | result | { password: string } | { ok: boolean, … } | 400 password missing or too short; 404 user not found | | authn.changePassword | Change own password | identity | result | { currentPassword: string, newPassword: string } | { ok: boolean, … } | 400 wrong current password, missing fields, or new one too short; 401 not authenticated | | authn.deactivateUser | Deactivate a user (ends their sessions) | params.id | result | – | { ok: boolean, … } | 400 cannot deactivate yourself; 404 user not found; 409 the last active admin cannot be deactivated (LAST_ADMIN) | | authn.activateUser | Activate a user | params.id | result | – | { ok: boolean, … } | 404 user not found | | authn.cleanupSessions | Remove expired sessions | – | result | – | { removed?: number, … } | – |

Used by 69 of 82 pipelines in examples/minimal.