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

@kblockai/sdk

v0.1.0-rc.1

Published

K-Block v0.1 TypeScript SDK: signed, content-addressed K-Objects, self-certifying identities (KIDs), delegations, encryption, workflows, portable receipts, relay transports and KBlockParticipant

Readme

@kblockai/sdk

Verify K-Block receipts offline, independently of K-Block. A receipt is a portable .kbundle file that records a protected action: who requested it, who approved exactly which call, who executed it and on whose behalf, all signed. This package checks every signature and every step itself.

The package also implements the K-Block v0.1 protocol for protocol participants: signed, content-addressed K-Objects, self-certifying identities (KIDs), scoped delegations, schema-driven workflows and portable receipts. K-Block is not a blockchain: there is no ledger, no consensus and no token.

Pre-release (0.1.0-rc.1). Most developers need this package only to verify receipts. Agents call the K-Block Gateway with @kblockai/client (Node.js) or kblock (Python); neither depends on this package.

Install

npm install --save-exact @kblockai/[email protected]
  • Node.js 22 or later (tested on Node.js 22.17), and current browsers (see "Browser support").
  • ESM only; TypeScript declarations included. Runtime dependencies: only @noble/curves, @noble/hashes and @noble/ciphers.
  • Entry points: @kblockai/sdk/verify (receipt verification only), @kblockai/sdk (the whole protocol) and @kblockai/sdk/testing (test helpers, never for production).
  • TypeScript: module / moduleResolution nodenext (or bundler with a bundler); the subpaths need one of them. The declarations use the global fetch and WebSocket types: include the DOM lib, or types: ["node"] with @types/node 22 or later.

Verify a receipt

verify_receipt.mjs, a complete program:

import { readFile } from "node:fs/promises";
import { renderText, verifyBundleJson } from "@kblockai/sdk/verify";

const [file, gatewayKid] = process.argv.slice(2);
if (!file) {
  console.error("usage: node verify_receipt.mjs <receipt.kbundle> [<gateway KID>]");
  process.exit(2);
}

const report = verifyBundleJson(await readFile(file, "utf8")); // never throws on invalid input
console.log(renderText(report)); // the seven checks, then RESULT: VALID or RESULT: INVALID

// VALID means the bundle is complete and consistent, and every object in it is signed by the keys its
// identity documents list. Whether YOUR Gateway issued it is a separate question: compare the issuer
// with the Gateway KID that K-Block gave you.
const fromGateway = gatewayKid === undefined || report.issuer === gatewayKid;
if (!fromGateway) console.log(`issuer ${report.issuer} is not the Gateway identity ${gatewayKid}`);
process.exit(report.valid && fromGateway ? 0 : 1);
node verify_receipt.mjs receipt.kbundle "<your Gateway's KID>"

renderText(report) returns the text report: the receipt and its issuer, what happened (outcome, who requested, approved and executed the call, on whose behalf, the delegations, the result's digest), the seven checks (Bundle format, Identity chains, Signature chain, Receipt coverage, Graph integrity, Workflow & authorization, Receipt summary), warnings and errors, then RESULT: VALID or RESULT: INVALID, and the notes. report.valid is true only when all seven checks pass and nothing was found.

  • verifyBundleJson(text, options?) parses strictly and verifies; verifyBundle(value, options?) takes an already parsed value. Both return a report and never throw on invalid input.
  • The report: valid, checks ({ name, status: "VALID" | "INVALID" | "SKIPPED", detail? }), issuer, issued_at, outcome, summary (derived by the verifier itself), path, actors, attestations, errors, warnings, notes. report.toJSON() is identical to the JSON report of the K-Block reference implementation.
  • KReceipt.verify(bundle) runs the same verification and flattens its verified summary (who did what): requestActor, proposer, approvedBy, executor, onBehalfOf, outcome, issuedAt.
  • Options: trustedAttesters (KIDs whose attestations, such as "executed", you choose to trust), knownIdentities (identity documents you obtained independently, for key freshness), maxIdentityKeys (a budget for bundles from untrusted parties; beyond it the bundle is invalid with TOO_LARGE), workflows (the accepted workflow definitions; the built-ins by default) and verify.now (a Timestamp, toTimestamp(…), for reporting expired objects; it does not change validity).
  • Kid.parse and parseObjectJson, for the KIDs and identity documents of your own configuration, throw ProtocolError on invalid input.

What a valid receipt proves

  • Each covered object was signed by its actor, with a key that the verifier's identity view lists as valid at the object's asserted time, and was not altered after signing.
  • The committed path from the result back to the request is exactly what was signed, with nothing unrelated attached.
  • Each step was allowed by the named workflow (roles, guards, states, causal order).
  • Who requested, who proposed, who approved exactly which proposal (by its content hash), who executed, and on whose behalf under which delegation chain.
  • The delegation granted the action within its constraints and time window.
  • The result's terms equal the approved terms, and the result payload has the stated digest.

In a receipt of a K-Block Gateway, the request, the proposal, the execution and the result are signed by the Gateway's identity on behalf of the organization (under the delegation the organization signed with its own key), and an approval by the approver's personal key; the agent itself signs nothing. Which agent and which API key made the call is the Gateway's own signed statement in the request.

What it does not prove

  • That the real-world effect happened. A result is the executor's signed claim. Only an attestation from an attester you trust (trustedAttesters) adds evidence, and only as much as the attester is worth.
  • Which deployment issued it. A bundle signed with fresh keys is consistent with the identity documents it carries. Compare report.issuer (and the signers) with KIDs you know independently, such as your Gateway's KID, as verify_receipt.mjs does.
  • When things happened. Timestamps are asserted by the signers; only causal order is checked.
  • That nothing conflicting exists outside the bundle. A bundle cannot show the absence of a cancellation, a revocation, a newer identity document (unless you pass knownIdentities) or a second consumer of the same approval.
  • That the issuer is honest or complete, or that self-asserted identity attributes (such as an actor's type) are true.

Security and trust model

  • Verification trusts neither the transport nor the receipt's issuer, K-Block included: it re-verifies every signature, identity chain, delegation and workflow transition, derives the summary itself and compares it with the issuer's claims.
  • Private keys stay local: a LocalIdentity signs in-process, and only public identity documents are published or embedded in bundles. exportSecrets() returns private keys: store them encrypted and never log them. For hardware-held keys, implement the Signer interface.
  • Relays and transports are untrusted: they can withhold or delay objects, never forge, alter or re-attribute them. Every participant verifies what it receives.
  • A service that acts on objects as they arrive must reject stale or future-dated objects (checkFreshness), transitions from expired parents (checkParentNotExpired) and replays (ReplayGuard), and should evaluate the whole thread, not just a path.
  • Disclosures placed in a bundle can be read by anyone who holds the bundle.

Protocol-level API

The package root exports the whole protocol. KBlockParticipant is a protocol participant over a relay: it hides canonicalization, nonces, IDs and signatures, verifies everything it receives, and checks every object it creates against the thread before publishing (preflight), so mistakes fail fast with the error code a relay or verifier would report. From protocol_participant.mjs, a complete example program:

import { KBlockParticipant, KReceipt, LocalIdentity, MemoryRelay, ProtocolError } from "@kblockai/sdk";

const relay = new MemoryRelay(); // in-process; RelayClient talks to a K-Block relay over HTTP

const alice = new KBlockParticipant({ identity: LocalIdentity.generate("human"), transport: relay });
const bot = new KBlockParticipant({ identity: LocalIdentity.generate("agent"), transport: relay });
await alice.register(); // publishes identity documents (public keys only)
await bot.register();

// Alice gives the agent scoped, time-limited authority, then a task.
const delegation = await alice.delegations.create({
  delegate: bot.kid,
  permissions: ["hotel.search", "hotel.book"],
  constraints: { maxAmount: { amount: "300", currency: "USD" } },
  expiresIn: 24 * 3600,
});
const task = await alice.tasks.create({
  assignedTo: bot.kid,
  payload: { instruction: "Find me a hotel under $300", budget: { amount: "300", currency: "USD" } },
});

// The agent proposes exact terms.
const terms = { hotel: "Hotel X", check_in: "2026-10-01", nights: 1, price: { amount: "250", currency: "USD" } };
const proposal = await bot.proposals.create({ task, summary: "Hotel X, 1 night, 250 USD", terms });

// Every participant checks what it creates against the thread before publishing it: the agent cannot
// approve its own proposal, so the SDK refuses locally with the protocol's error code.
try {
  await bot.approvals.approve(proposal);
} catch (e) {
  if (e instanceof ProtocolError) console.log("refused:", e.code); // "UNAUTHORIZED_ACTOR"
  else throw e;
}

// Alice approves that proposal (bound by its content hash).
const approval = await alice.approvals.approve(proposal, { note: "Book it." });

// The agent executes and records the result on Alice's behalf, under the delegation.
const execution = await bot.executions.create({ parent: approval, action: "hotel.book", delegation: delegation.id });
const result = await bot.results.create({ parent: execution, delegation: delegation.id, output: { confirmation: "HX-4471" } });

// A portable receipt: it verifies offline, without trusting the relay or the issuer.
const bundle = await alice.receipts.issue(task.id, result.id);
const v = KReceipt.verify(bundle);
console.log("receipt:", v.valid, v.outcome); // true "succeeded"
console.log("approved by alice:", v.approvedBy === alice.kid, "executed by bot:", v.executor === bot.kid, "on behalf of alice:", v.onBehalfOf === alice.kid);

Where a method takes a task, proposal, approval or execution, you can pass the object or its ID (an ID is fetched and verified). Recipients come from the workflow roles, terms are copied from the approved proposal, and onBehalfOf is the principal at the top of the delegation chain.

Receiving: participant.subscribe(handler) delivers verified objects from a relay over WebSocket (backlog first, duplicates dropped, at-least-once, acknowledged after the handler resolves); participant.inbox.list() and inbox.ack() poll; participant.threads.get(id) returns a locally verified view of a whole thread.

Errors are ProtocolError (with isProtocolError(e, code?)): a protocol or verification failure, with the reference implementation's codes, such as ID_MISMATCH, INVALID_SIGNATURE and UNAUTHORIZED_ACTOR. A relay that refuses a request or cannot be reached gives RelayError (with .status); errorCode(e) reads the code from either. ProtocolError is unrelated to @kblockai/client's KBlockProtocolError, which means a Gateway answer that is not a K-Block answer.

Transports: RelayClient talks to a K-Block relay over fetch and WebSocket (both injectable), signing its requests and refusing answers that do not match them; MemoryRelay is an in-process relay with the same checks, for tests and demos.

Building blocks:

| Area | API | |---|---| | Objects | ObjectBuilder, parseObject / parseObjectJson, verifyObject, canonicalize (KB-JCS) | | Identities | LocalIdentity, IdentityChain, IdentityRegistry | | Delegations | verifyAuthority, checkConstraints, permissionMatches | | Encryption | encrypt, decrypt, verifyDisclosure (X25519, HKDF-SHA256, ChaCha20-Poly1305) | | Workflows | WorkflowRegistry, ObjectSet, verifyGraph | | Live receivers | checkFreshness, checkParentNotExpired, ReplayGuard | | Receipts | issueReceipt, verifyBundle, bundleToJson | | Relay authentication | AuthFields, authenticate, SignatureCache |

Encryption: let ObjectBuilder draw a fresh encryption seed. A caller-supplied seed exists only for deterministic test vectors; reusing a seed breaks confidentiality.

Browser support

The library imports no Node.js modules. On Node.js, when process.getBuiltinModule passes a self-test, Ed25519 signing, the group equation of verification and SHA-256 of large inputs use node:crypto; every strictness check stays in JavaScript, and browsers use @noble only. Otherwise it relies on crypto.getRandomValues, and on fetch and WebSocket for RelayClient only.

The package ships ES2022 JavaScript: a bundler must target ES2022 or transpile it. A browser bundle of @kblockai/sdk/verify was run in a current Chromium with no polyfill. @noble calls Object.hasOwn while it loads, so engines older than Chrome 93, Firefox 92 and Safari 15.4 need a polyfill for it.

Testing helpers

@kblockai/sdk/testing exports DemoActors, runHotelDemo and DEMO_WORKFLOW, which run the protocol's example workflow end to end. Never use them in production: DemoActors.deterministic builds identities from secret keys that are public.

Versioning

0.1.0-rc.1 is a pre-release. Package versions follow semver; VERSION ("0.1") is the protocol version and is independent of the package version.

License

K-Block SDK License (proprietary); see the LICENSE file in this package.