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

@worker-protocol/conformance

v0.4.0

Published

Point it at a Worker's base URL, get a report of what it complies with

Readme

@worker-protocol/conformance

Point it at a Worker's base URL, get a report of what it complies with.

worker-protocol is an open specification for Workers that can be seen, operated and given work by people who did not build them. HTTP and JSON Schema, no runtime. A Worker describes itself in a Descriptor served at /.well-known/worker-protocol — the one address this protocol fixes — and declares there which of its Capabilities it implements.

This is the tool that checks whether it does what it says. It is also how the name is earned: the protocol is Apache-2.0, but a claim that something speaks worker-protocol is one this project vouches for, and a report from here is what stands behind it.

Run it

npx @worker-protocol/conformance https://fleet.example.com
worker-protocol-conformance <base-url> [options]

  --credential <token>  Presented as `Authorization: Bearer <token>`.
                        Prefer WORKER_PROTOCOL_CREDENTIAL: argv is visible to
                        every process on the machine, and a CI log often keeps it.
  --may-perform         Allow POSTs to Actions. Off by default: an Action is an
                        operation somebody's operators chose to expose, and a tool
                        pointed at a Worker to inspect it does not perform work on
                        it uninvited. Rules needing one report notExercised.
  --json                Write the report to stdout as JSON, and nothing else.
  -h, --help            This.

Exit: 0 nothing failed, 1 a rule failed, 2 the run could not be made.

Everything but actions is a read, and a read leaves the Worker as it found it. That is why --may-perform is a decision you make rather than a default: the rules that need a POST report notExercised with that as the reason until you do.

From TypeScript

import { tally, verify } from "@worker-protocol/conformance";

const report = await verify({
  baseUrl: "https://fleet.example.com",
  credential: process.env.WORKER_PROTOCOL_CREDENTIAL,
  mayPerform: true,
  arrangement: {
    safeAction: { name: "answer-check", input: { vehicle: "ABC-123", reachable: true } },
    secondCredential: process.env.SECOND_CREDENTIAL,
  },
});

const counts = tally(report.results);
for (const { rule, verdict, detail } of report.results) {
  if (verdict === "fails") console.error(`${rule.id} (${rule.file}): ${detail}`);
}

verify() runs in any runtime with a fetch — Node, Bun, Deno, a Cloudflare Worker, a Vercel edge function, a Convex action — so a Control Tower can verify the Workers it enrolls from inside its own runtime. The library imports no Node built-in and reads no file: the rule universe is compiled into the module, so a bundler that inlines the package leaves nothing behind. Only the command line needs Node. This package's own suite runs verify() on workerd with no Node compatibility enabled.

verify also takes a fetch of your own, for a test, for a caller that needs its own agent, or for a Worker reached in-process through its app.fetch rather than over the network.

The verdicts, and why there are five

A report covers every rule the edition defines, not only the ones a run exercised. A rule that nothing claimed is not silence — it says under its own name why nothing claimed it.

| Verdict | What it means | |---|---| | passes | The check ran and the Worker satisfied it. | | fails | The check ran and the Worker did not. Exit 1. | | notExercised | The Worker declares no such Capability, or the check needs a Worker arranged to be observed and this one is not. A gap somebody can close. | | unverified | The rule's subject is the Worker, and no party outside it can observe a violation. | | otherSubject | The rule binds a verifier, a Control Tower, a consumer or an issuer — not a Worker. This tool never contacted whoever it obliges. |

notExercised never fails the run, and it is deliberately not the same word as unverified: they read alike on a page and are opposite facts. A report that counted either as compliance would be vouching for something nobody checked.

Each result carries the rule's id, the specification file that defines it, whether the rule is required or recommended, and one line saying why for every verdict but passes. The ids are fixed from edition 0.1 on: a rewrite that could change a verdict takes a new id and withdraws the old, so a report stays true however long after it was produced somebody reads it.

Arranging a Worker so more can be seen

Some rules have no ordinary witness: nothing a tool can do to an unarranged Worker will ever see a violation. An Action that succeeds, an input refused on the Worker's own rules, a second credential issued to the same holder, a Worker that started moments ago. The arrangement cannot come from the protocol — putting test scaffolding into a Descriptor would make every Worker in the network carry it — so it arrives the way the base URL and the credential do: out of band, from whoever set it up.

arrangement takes safeAction, refusedInput, asyncAction, secondCredential, consumerCredential, unprivilegedCredential, justStarted, replaceableSettings and publishedEvent. Anything not arranged reports notExercised naming what was missing.

Editions

The verifier declares which edition it holds, and the report carries both that and what the Worker declared. A verifier that does not hold the Worker's MAJOR verifies nothing and reports that it is the one that is behind — rather than failing a Worker for a surface added after this tool was built.

The rule universe travels inside this package, generated from the specification, and universe() hands it back: the rules, the error codes, and the map from a place inside a document to the rule that governs it — which is how a report names the obligation that was broken rather than announcing that a document is invalid. It ships twice from one generation: compiled into the library, and as rules.json for a reader outside JavaScript.

What standing it has

Nothing here carries behavior of its own. Every check reports against a rule id, and a check that observed something the specification does not require would be this package making the standard. When this tool and the specification disagree, the specification is right and this is the bug.

Fixing what it reports, with a coding agent

npx skills add rowing-tech/worker-protocol --skill worker-protocol

An Agent Skill carrying the protocol in any language: what each rule id means, where its file is, the surface an implementer without an SDK writes by hand, and the gotchas behind the failures this tool reports most. --all adds a second one for TypeScript on Hono.

Related packages

  • @worker-protocol/schemas — the Zod objects that generate the normative JSON Schemas.
  • @worker-protocol/hono — mount(): implement an interface and get every address, header and refusal this protocol fixes.
  • @worker-protocol/client — consume(): read a Worker, and take work from it.

License and name

Apache-2.0, patent grant included — implement the protocol in any product, commercial or not, without asking anyone. The name is not part of that grant (Apache-2.0 §6).