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

@fortsignal/sdk

v0.1.13

Published

Intent verification infrastructure for agents and human-authorized actions.

Readme

@fortsignal/sdk

Cryptographic proof that a specific action was authorized with specific parameters — not just that someone logged in.

The official TypeScript SDK for FortSignal. Works for humans and AI agents.

Live demo · Docs · fortsignal.com


The problem

Authentication proves who logged in. It doesn't prove what they authorized afterward. A stolen session token, a compromised server, or a rogue AI agent can execute any action with no further proof.

FortSignal closes that gap. Every action requires a fresh hardware-backed signature bound to the exact parameters:

challenge = SHA-256(nonce : action : amount : recipient : from : metadata)

If any parameter changes after the user approves — including server-side tampering — verification returns deny: parameters_tampered. Patent pending April 2026.


How it works

FortSignal verifies that the exact parameters a user or agent approved are the same parameters that execute. Every action gets a fresh hardware-signed approval — cryptographically bound to the action, amount, recipient, and any other fields you define.

Three separate layers

Action parameters (action, amount, recipient, and optionally from, metadata) describe the specific action being requested. They are sent per-request and cryptographically signed — proof that the exact values were approved at that moment.

Policy constraints are separate. Policy profiles are persistent rules you configure once in your FortSignal dashboard and attach to users or agents. After the signature passes, FortSignal checks the action parameter values against those rules — allowedActions, maxAmountPerAction, allowedRecipients. A valid signature is not enough on its own; if the action violates any policy constraint, FortSignal returns decision: deny.

For agents there is a third layer: the delegation must be active and not expired. All three must pass — valid signature, active delegation, within policy — for the decision to be allow.

Installation

npm install @fortsignal/sdk

Human interaction required — if humans approve actions via passkey in your app, install the WebAuthn browser library for your frontend:

npm install @simplewebauthn/browser

Agent only (no human interaction) — if agents act autonomously within their policy, no browser library is needed. Agents sign with an Ed25519 private key on the server — no WebAuthn, no browser, no additional dependencies.

Get an API key

Sign up at fortsignal.com/signup. You'll get a fs_live_... key immediately after checkout.


Human Flow

Step 1 — Initialize the client (server-side)

import { FortSignal } from '@fortsignal/sdk'

const client = new FortSignal({ apiKey: process.env.FORTSIGNAL_API_KEY })

Step 2 — Register a user's passkey (one time per user)

Call this when the user sets up their account or enables high-security actions.

// Server: start registration
const options = await client.register.start({
  userId: 'user_123',
  username: '[email protected]',
})

// Browser: prompt the user to create a passkey
import { startRegistration } from '@simplewebauthn/browser'
const attestation = await startRegistration({ optionsJSON: options })

// Server: complete registration
await client.register.complete({
  userId: 'user_123',
  challenge: options.challenge,
  attestation,
})

Step 3 — Authorize an action

// Server: start a challenge before the action executes
const options = await client.challenge.start({
  userId: 'user_123',
  action: 'transfer',
  amount: 500,              // optional — defaults to 0 for non-monetary actions
  recipient: '[email protected]',
  from: '[email protected]',
  metadata: { orderId: 'ord_123' }, // optional — must be a JSON object, not a string
})

// Browser: prompt the user to sign with their passkey
import { startAuthentication } from '@simplewebauthn/browser'
const assertion = await startAuthentication({ optionsJSON: options })

// Server: verify the signature
const result = await client.challenge.verify(assertion)

if (result.decision === 'allow') {
  // result.signalId — store this as your audit receipt
  await executeTransfer()
} else {
  // result.reason — why it was denied:
  // 'policy_not_found'       — user has a record in /org/users but no policy assigned
  // 'policy_expired'         — policy expiresAt has passed
  // 'action_not_allowed'     — action not in policy allowedActions
  // 'amount_exceeds_policy'  — amount over policy maxAmountPerAction
  // 'recipient_not_allowed'  — recipient not in policy allowedRecipients
  // 'parameters_tampered'    — params changed after challenge was issued
  // 'invalid_challenge'      — expired or already used
  throw new Error(result.reason)
}

Agent Flow

Step 1 — Register an agent's public key (one time per agent)

Generate an Ed25519 keypair for your agent and register the public key.

await client.agent.register({
  agentId: 'my-agent-01',
  publicKey: agentPublicKeyBase64url, // Ed25519 public key, base64url encoded
})
// Agent now appears in your dashboard — assign a policy before it can act

Step 2 — Assign a policy (dashboard)

Go to your FortSignal dashboard and assign a policy to the agent. The policy defines allowed actions, amount caps, and approved recipients. Set an expiry for the delegation.

Policy assignment requires owner authentication and cannot be done via API key. This is intentional — a compromised API key cannot grant or revoke agent permissions.

Step 3 — Verify each agent action

The agent starts a challenge, signs it with its Ed25519 private key, then submits the signature.

// 1. Start a challenge — FortSignal checks delegation and policy before issuing it
const { challenge } = await client.agent.startChallenge({
  agentId: 'my-agent-01',
  action: 'transfer',
  amount: 250,
  recipient: 'acct_456',
})

// 2. Sign the challenge bytes with your agent's Ed25519 private key
const challengeBytes = Buffer.from(challenge, 'base64url')
const sigBytes = await crypto.subtle.sign('Ed25519', privateKey, challengeBytes)
const signature = Buffer.from(sigBytes).toString('base64url')

// 3. Verify
const result = await client.agent.verify({
  agentId: 'my-agent-01',
  challenge,
  signature,
})

if (result.decision === 'allow') {
  // result.signalId — audit receipt
  // result.delegationId — traces back to the human who approved this agent
  await executeAction()
} else {
  // result.reason — why it was denied:
  // 'delegation_invalid'     — delegation revoked, expired, or never approved
  // 'policy_not_found'       — agent has a delegation but the policy no longer exists
  // 'policy_expired'         — policy expiresAt has passed
  // 'action_not_allowed'     — action not in policy allowedActions
  // 'amount_exceeds_policy'  — amount over policy maxAmountPerAction
  // 'recipient_not_allowed'  — recipient not in policy allowedRecipients
  // 'verification_failed'    — Ed25519 signature does not match registered key
}

Error Handling

Deny decisions are not errors — they come back in the response body with decision: 'deny':

const result = await client.challenge.verify(assertion)

if (result.decision === 'deny') {
  // result.reason — why it was denied
  console.error(result.reason)
}

HTTP errors (bad API key, rate limit, server error) throw a FortSignalError:

import { FortSignal, FortSignalError } from '@fortsignal/sdk'

try {
  const result = await client.challenge.start({ ... })
} catch (err) {
  if (err instanceof FortSignalError) {
    console.error(err.code)   // e.g. 'invalid_api_key'
    console.error(err.status) // e.g. 401
  }
}

API Reference

client.register

| Method | Description | |--------|-------------| | register.start({ userId, username }) | Begin passkey registration | | register.complete({ userId, challenge, attestation }) | Complete passkey registration |

client.challenge

| Method | Description | |--------|-------------| | challenge.start({ userId, action, amount?, recipient, from?, metadata?, requireBiometric? }) | Start a challenge. amount defaults to 0 if omitted — safe to omit for non-monetary actions. | | challenge.verify(assertion) | Verify the signed assertion |

client.agent

| Method | Description | |--------|-------------| | agent.register({ agentId, publicKey }) | Register an agent's Ed25519 public key | | agent.startChallenge({ agentId, action, amount?, recipient, from?, metadata? }) | Start a challenge for an agent action. amount defaults to 0 if omitted. | | agent.verify({ agentId, challenge, signature }) | Submit the signed challenge |

Dashboard-auth endpoints (not callable via API key — use from your dashboard session):

| Endpoint | Description | |----------|-------------| | POST /agent/delegate | Approve a delegation — pick a policy and set expiry. | | POST /agent/revoke | Revoke an agent's active delegation. | | GET /agent/list | List all agents and their delegation status. |


Requirements

Full Documentation

fortsignal.com/docs