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

@dorigjo/besa

v0.1.0

Published

Cryptographic execution evidence for AI-agent tool calls: signed manifests, admission decisions, and tamper-evident receipts.

Readme


The problem

AI agents are calling real systems — CRMs, payment APIs, deployment pipelines, databases, code repositories. Every call is a real action with real consequences and no natural chokepoint.

When something goes wrong — or when compliance asks — your team needs to answer:

  • What was this agent actually declared to do?
  • Was this action inside policy before it happened?
  • Was it admitted or blocked — and why?
  • Can you show an auditor a tamper-evident proof?

Most teams today cannot answer these questions. There is no gate. There is no record. There is no proof.


What Besa does

Besa is the execution control plane for AI-agent tool calls.

Gate before execution: Besa checks whether the tool is declared in a signed manifest, policy-approved, within budget, and scoped to the requesting agent. Undeclared tools are denied. Destructive high-risk tools are blocked by default. Budget overruns are stopped.

Sign the decision: Every admission — allow or deny — produces a signed cryptographic receipt recording the tool name, manifest hash, request fingerprint, reason code, and signing key. Not a log. Signed proof.

Verify the chain: The signed manifest, admission decision, and receipt form a complete, tamper-evident evidence chain. Any field change causes verification to fail closed.

Early access. 0.1.0 is the first public release — local, single-host tamper-evidence for AI-agent tool calls. Built for development, CI integration, and early runtime control. See Limitations.


The control flow

manifest.yaml
  → besa sign              # declare and sign tool capabilities, risks, scopes
  → manifest.signed.json   # tamper-evident capability declaration
  → besa trust add         # pin the publisher's public key
  → besa verify            # verify signature against trust anchor
  → besa admit <tool>      # policy gate: allow or deny (fail-closed)
  → besa receipt <tool>    # enforce budget, issue signed execution receipt
  → besa verify-receipt    # verify the complete evidence chain

Every step produces a durable, independently verifiable artifact. Changing any field in any artifact causes verification to fail closed.


What you get

Signed capability declarations

Every tool's declared capabilities, risk level, allowed scopes, and budget limits are captured in a manifest and signed with Ed25519. Any change after signing is detectable.

Policy-gated tool calls

Besa checks every tool call before it happens. Destructive high-risk tools are blocked by default. Budget limits cap runaway usage. Per-agent grant scoping restricts access to specific tools. Undeclared tools are denied.

Signed allow/deny decisions

Every admission decision — allow or deny — produces a signed receipt recording the tool name, manifest hash, request fingerprint, decision, and timestamp. Not a log. Proof.

Verifiable evidence chain

Sign → verify → admit → receipt → verify-receipt. Each step is independently verifiable. The signed manifest, admission decision, and receipt form a complete, tamper-evident chain.

CI/CD gate

Run Besa in your CI pipeline to verify that manifests are signed, that declared tools pass policy, and that undeclared or high-risk tools fail the build. See docs/CI_GATE.md.


Install

npm install @dorigjo/besa

Pin the exact version explicitly:

npm install @dorigjo/[email protected]

Set the key passphrase before any signing operation:

export BESA_KEY_PASSPHRASE="your-passphrase-at-least-16-bytes"

Build from source

git clone https://github.com/dorigjo/besa
cd besa
npm ci
npm run build

Quickstart

# Show available commands
npx besa --help

# Generate or load the local signing key
npx besa keys

# Validate the manifest (dry-run, no signing)
npx besa load examples/manifest.yaml

# Sign the manifest
npx besa sign examples/manifest.yaml

# Verify the signature
npx besa verify examples/manifest.signed.json

# Admission gate (fail-closed dry-run)
npx besa admit examples/manifest.signed.json crm.lookup   # → allow
npx besa admit examples/manifest.signed.json crm.delete   # → deny RISK_BLOCKED

# Issue a signed execution receipt (consumes budget)
npx besa receipt crm.lookup examples/manifest.signed.json \
  --request examples/request.json

# Verify the receipt chain
npx besa verify-receipt .besa/receipts/<id>.json \
  examples/manifest.signed.json

PowerShell

$env:BESA_KEY_PASSPHRASE = "your-passphrase-at-least-16-bytes"
npx besa keys
npx besa sign examples/manifest.yaml
npx besa verify examples/manifest.signed.json
npx besa admit examples/manifest.signed.json crm.lookup
npx besa receipt crm.lookup examples/manifest.signed.json `
  --request examples/request.json

$receipt = Get-ChildItem .\.besa\receipts\*.json |
  Sort-Object LastWriteTime -Descending | Select-Object -First 1
npx besa verify-receipt $receipt.FullName examples/manifest.signed.json

Consumer trust (separate system)

# Pin the publisher's public key
npx besa trust add examples/manifest.signed.json \
  --trust consumer-trust.json

# Verify against a pinned trust anchor (fails without it)
npx besa verify examples/manifest.signed.json \
  --trust consumer-trust.json

Key rotation

npx besa keys rotate

npx besa trust apply .besa/rotations/<rotation>.json \
  --trust consumer-trust.json

npx besa sign examples/manifest.yaml   # re-sign under the new key

The previous key becomes retired: artifacts signed before rotation remain verifiable, but new admissions under that key are denied. trust revoke invalidates a key for all artifacts, current and historical.


CI/CD gate

Besa can run as a verification gate in GitHub Actions or any CI pipeline. A failed manifest signature or a denied tool call fails the build.

- name: Verify manifest
  run: |
    npx besa verify examples/manifest.signed.json
    npx besa admit examples/manifest.signed.json crm.lookup

See docs/CI_GATE.md for a complete example workflow.


Runtime gateway pattern

Besa's SDK can sit on the call path of an agent runtime. Before the agent calls a tool, the gateway calls admit() or admitAndConsume() from @dorigjo/besa. If the decision is deny, the tool call never reaches the upstream system.

import { admit, verifyTrustedSignedManifest } from "@dorigjo/besa";

// Before forwarding any agent tool call:
const verified = verifyTrustedSignedManifest(signedManifest, trustStore);
if (!verified.valid) return { decision: "deny", reasonCode: verified.reasonCode };

const decision = admit(signedManifest.manifest, toolName, currentCount);
if (decision.decision === "deny") return decision;

// Only here: forward the call to the actual tool

See examples/agent-gateway/ for a working skeleton.


Commands

| Command | Description | |---|---| | besa keys | Generate or display the local signing key | | besa keys rotate | Rotate to a new key, archive the previous | | besa trust add <manifest> | Pin the manifest's public key as a trust anchor | | besa trust apply <rotation> | Apply a signed rotation proof | | besa trust revoke <key-id> | Revoke a trust anchor | | besa trust list | List all trust anchors and their status | | besa load <manifest> | Validate a manifest without signing | | besa sign <manifest> | Sign a manifest | | besa verify <manifest> | Verify a signed manifest against the trust store | | besa admit <manifest> <tool> | Gate: check policy + budget (fail-closed, dry-run) | | besa receipt <tool> <manifest> | Enforce budget and issue a signed execution receipt | | besa verify-receipt <receipt> <manifest> | Verify the receipt trust chain |

All commands accept --trust <trust.json> to use a consumer-side trust store. admit and receipt also accept --agent <id> --grants <grants.yaml>.


The execution receipt

{
  "receiptId": "rcpt_2d7942c7-8f70-4984-9c3f-24876acfd860",
  "manifestHash": "ea7e9ca22d199f40281cdf9e5d6145440c6c7d6bfbe94157c4b1da5527054410",
  "toolName": "crm.lookup",
  "decision": "allow",
  "reasonCode": "ALLOWED",
  "timestamp": "2026-06-19T10:00:00.000Z",
  "requestHash": "b27b80d1227c167a6fca199778645daa77d20a8087782fc48802d11d6281c920",
  "publicKeyId": "f68668614543c4896cf8cee418492f1a4df1f1acdba8850f94728b8a94cf90fe",
  "algorithm": "ed25519",
  "signature": "<base64-ed25519-signature>"
}

publicKeyId is the full SHA-256 fingerprint of the Ed25519 public key DER bytes. Changing any field causes verify-receipt to fail closed.


Admission reason codes

| Code | Meaning | |---|---| | ALLOWED | Tool call admitted | | TOOL_NOT_FOUND | Tool not declared in the signed manifest | | RISK_BLOCKED | Destructive high-risk tool blocked by policy | | BUDGET_EXCEEDED | Call count reached the manifest budget limit | | TOOL_NOT_GRANTED | Agent not granted access to this tool | | AGENT_NOT_FOUND | Agent ID not listed in the grant set | | E_KEY_UNTRUSTED | Signing key not in the trust store | | E_KEY_RETIRED | Key retired; new admissions under it are denied | | E_KEY_REVOKED | Key revoked; all operations denied |


SDK

import {
  admit,
  addTrustAnchor,
  applyKeyRotation,
  canonicalize,
  checkTrustedKey,
  createKeyRotation,
  createReceipt,
  generateKeyPair,
  hashRequest,
  loadManifest,
  signManifest,
  validateManifest,
  validateReceipt,
  verifyReceiptDetailed,
  verifySignedManifest,
  verifyTrustedSignedManifest,
} from "@dorigjo/besa";

Security model

Besa provides tamper-evidence, not secrecy.

A signed manifest proves that the declared tool capabilities, scopes, risks, and metadata have not changed since signing. A signed receipt creates a tamper-evident record that a specific admission decision was made at a specific time under a specific key.

Cryptography:

  • Ed25519 signatures (256-bit security) on the complete artifact envelope
  • AES-256-GCM key encryption at rest with scrypt KDF (N=32768, r=8, p=1)
  • SHA-256 manifest hashing and full 256-bit (64-hex-character) SHA-256 public key fingerprints
  • Domain-separated signature messages (besa:<domain>:v1\0<canonical-json>)
  • Timing-safe public key comparison via crypto.timingSafeEqual

Fail-closed behavior:

  • Verification fails on any signature, hash, or key mismatch
  • Admission fails closed on invalid policy, manifest, or call count
  • Trust store rejects symlinks, unknown fields, and duplicate key IDs
  • Trust store paths must end in .json
  • Tool names are restricted to ASCII printable characters

See SECURITY.md and docs/THREAT_MODEL.md.


Release gates

npm ci
npm run build
npm test          # 56 tests
npm run smoke     # end-to-end trust flow
npm run test:package
npm pack --dry-run

Limitations

Besa 0.1.0 is a first public release (early access). The core execution control artifacts — signed manifests, signed execution receipts, and the verification chain — are production-quality cryptography. The surrounding infrastructure is not yet production-grade.

Current limitations:

  • Local key storage only; no hosted key management or HSM integration
  • File-based meter and trust state; intended for single-host use
  • No distributed replay protection across machines or environments
  • No external trusted timestamp authority
  • No hosted verifier, receipt retention, or SIEM export
  • No production identity or multi-user authorization
  • No formal compliance certification (SOC 2, ISO 27001, EU AI Act)

The signed manifest, admission gate, and receipt chain are designed to remain forward-compatible as the infrastructure matures. The policy contract you establish today will be verifiable against future infrastructure.


Roadmap

The path from local control plane to hosted infrastructure:

  1. Today (0.1.0): CLI gate, CI/CD integration, local enforcement, signed receipts
  2. Next: Hosted verifier API — consumers verify receipts without a local trust store
  3. Then: Hosted receipt retention — tamper-evident receipt log with export
  4. Then: Runtime gateway — HTTP proxy that gates agent tool calls in production
  5. Then: Enterprise control plane — org-level policy, SIEM export, HSM signing, multi-user

License

MIT