@worker-protocol/conformance 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +126 -0
  2. package/package.json +4 -4
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # @worker-protocol/conformance
2
+
3
+ Point it at a Worker's base URL, get a report of what it complies with.
4
+
5
+ **worker-protocol is an open specification for Workers that can be seen, operated and given work by
6
+ people who did not build them.** HTTP and JSON Schema, no runtime. A *Worker* describes itself in a
7
+ Descriptor served at `/.well-known/worker-protocol` — the one address this protocol fixes — and
8
+ declares there which of its Capabilities it implements.
9
+
10
+ This is the tool that checks whether it does what it says. It is also how the name is earned: the
11
+ protocol is Apache-2.0, but a claim that something *speaks worker-protocol* is one this project
12
+ vouches for, and a report from here is what stands behind it.
13
+
14
+ ## Run it
15
+
16
+ ```
17
+ npx @worker-protocol/conformance https://fleet.example.com
18
+ ```
19
+
20
+ ```
21
+ worker-protocol-conformance <base-url> [options]
22
+
23
+ --credential <token> Presented as `Authorization: Bearer <token>`.
24
+ Prefer WORKER_PROTOCOL_CREDENTIAL: argv is visible to
25
+ every process on the machine, and a CI log often keeps it.
26
+ --may-perform Allow POSTs to Actions. Off by default: an Action is an
27
+ operation somebody's operators chose to expose, and a tool
28
+ pointed at a Worker to inspect it does not perform work on
29
+ it uninvited. Rules needing one report notExercised.
30
+ --json Write the report to stdout as JSON, and nothing else.
31
+ -h, --help This.
32
+
33
+ Exit: 0 nothing failed, 1 a rule failed, 2 the run could not be made.
34
+ ```
35
+
36
+ Everything but `actions` is a read, and a read leaves the Worker as it found it. That is why
37
+ `--may-perform` is a decision you make rather than a default: the rules that need a POST report
38
+ `notExercised` with that as the reason until you do.
39
+
40
+ ## From TypeScript
41
+
42
+ ```ts
43
+ import { tally, verify } from "@worker-protocol/conformance";
44
+
45
+ const report = await verify({
46
+ baseUrl: "https://fleet.example.com",
47
+ credential: process.env.WORKER_PROTOCOL_CREDENTIAL,
48
+ mayPerform: true,
49
+ arrangement: {
50
+ safeAction: { name: "answer-check", input: { vehicle: "ABC-123", reachable: true } },
51
+ secondCredential: process.env.SECOND_CREDENTIAL,
52
+ },
53
+ });
54
+
55
+ const counts = tally(report.results);
56
+ for (const { rule, verdict, detail } of report.results) {
57
+ if (verdict === "fails") console.error(`${rule.id} (${rule.file}): ${detail}`);
58
+ }
59
+ ```
60
+
61
+ `verify` also takes a `fetch` of your own, for a test or for a caller that needs its own agent.
62
+
63
+ ## The verdicts, and why there are five
64
+
65
+ A report covers **every** rule the edition defines, not only the ones a run exercised. A rule that
66
+ nothing claimed is not silence — it says under its own name why nothing claimed it.
67
+
68
+ | Verdict | What it means |
69
+ |---|---|
70
+ | `passes` | The check ran and the Worker satisfied it. |
71
+ | `fails` | The check ran and the Worker did not. Exit 1. |
72
+ | `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. |
73
+ | `unverified` | The rule's subject is the Worker, and no party outside it can observe a violation. |
74
+ | `otherSubject` | The rule binds a verifier, a Control Tower, a consumer or an issuer — not a Worker. This tool never contacted whoever it obliges. |
75
+
76
+ `notExercised` never fails the run, and it is deliberately not the same word as `unverified`: they
77
+ read alike on a page and are opposite facts. A report that counted either as compliance would be
78
+ vouching for something nobody checked.
79
+
80
+ Each result carries the rule's id, the specification file that defines it, whether the rule is
81
+ `required` or `recommended`, and one line saying why for every verdict but `passes`. The ids are
82
+ fixed from edition 0.1 on: a rewrite that could change a verdict takes a new id and withdraws the
83
+ old, so a report stays true however long after it was produced somebody reads it.
84
+
85
+ ## Arranging a Worker so more can be seen
86
+
87
+ Some rules have no ordinary witness: nothing a tool can do to an unarranged Worker will ever see a
88
+ violation. An Action that succeeds, an input refused on the Worker's own rules, a second credential
89
+ issued to the same holder, a Worker that started moments ago. The arrangement cannot come from the
90
+ protocol — putting test scaffolding into a Descriptor would make every Worker in the network carry
91
+ it — so it arrives the way the base URL and the credential do: out of band, from whoever set it up.
92
+
93
+ `arrangement` takes `safeAction`, `refusedInput`, `asyncAction`, `secondCredential`,
94
+ `consumerCredential`, `unprivilegedCredential`, `justStarted`, `replaceableSettings` and
95
+ `publishedEvent`. Anything not arranged reports `notExercised` naming what was missing.
96
+
97
+ ## Editions
98
+
99
+ The verifier declares which edition it holds, and the report carries both that and what the Worker
100
+ declared. A verifier that does not hold the Worker's MAJOR verifies **nothing** and reports that it
101
+ is the one that is behind — rather than failing a Worker for a surface added after this tool was
102
+ built.
103
+
104
+ The rule universe travels inside this package as `rules.json`, generated from the specification, and
105
+ `universe()` hands it back: the rules, the error codes, and the map from a place inside a document
106
+ to the rule that governs it — which is how a report names the obligation that was broken rather
107
+ than announcing that a document is invalid.
108
+
109
+ ## What standing it has
110
+
111
+ **Nothing here carries behavior of its own.** Every check reports against a rule id, and a check
112
+ that observed something the specification does not require would be this package making the
113
+ standard. When this tool and the specification disagree, the specification is right and this is the
114
+ bug.
115
+
116
+ ## Related packages
117
+
118
+ - `@worker-protocol/schemas` — the Zod objects that generate the normative JSON Schemas.
119
+ - `@worker-protocol/hono` — `mount()`: implement an interface and get every address, header and
120
+ refusal this protocol fixes.
121
+ - `@worker-protocol/client` — `consume()`: read a Worker, and take work from it.
122
+
123
+ ## License and name
124
+
125
+ Apache-2.0, patent grant included — implement the protocol in any product, commercial or not,
126
+ without asking anyone. The name is not part of that grant (Apache-2.0 §6).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@worker-protocol/conformance",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "workerProtocolEdition": "0.1",
5
5
  "description": "Point it at a Worker's base URL, get a report of what it complies with",
6
6
  "license": "Apache-2.0",
@@ -9,7 +9,7 @@
9
9
  "url": "git+https://github.com/rowing-tech/worker-protocol.git",
10
10
  "directory": "packages/conformance"
11
11
  },
12
- "homepage": "https://github.com/rowing-tech/worker-protocol#readme",
12
+ "homepage": "https://github.com/rowing-tech/worker-protocol/tree/main/packages/conformance#readme",
13
13
  "bugs": "https://github.com/rowing-tech/worker-protocol/issues",
14
14
  "publishConfig": {
15
15
  "access": "public"
@@ -33,12 +33,12 @@
33
33
  "NOTICE"
34
34
  ],
35
35
  "dependencies": {
36
- "@worker-protocol/schemas": "0.1.0",
36
+ "@worker-protocol/schemas": "0.1.1",
37
37
  "zod": "^4.5.4"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "26.5.1",
41
- "@worker-protocol/client": "0.1.0",
41
+ "@worker-protocol/client": "0.1.1",
42
42
  "typescript": "7.0.2",
43
43
  "vitest": "5.0.0",
44
44
  "wrangler": "4.131.1"