@byollm/conformance 0.1.0-alpha.6 → 0.1.0-alpha.60

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.
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  > [!WARNING]
2
- > **Alpha (`0.1.0-alpha.6`) — under active development. Don't use this yet.**
2
+ > **Alpha (`0.1.0-alpha.60`) — under active development. Don't use this yet.**
3
3
  >
4
4
  > Install it deliberately: `npm install @byollm/conformance@alpha`.
5
5
  >
@@ -11,7 +11,109 @@
11
11
  > npm assigns `latest` on a first publish and won't let it be removed, so a
12
12
  > bare install resolves here too. This notice is the only guard — deliberately
13
13
  > not an npm deprecation, which would read as *abandoned* rather than *early*.
14
- > Ask for `@alpha` explicitly so your lockfile records that you meant to.
14
+ > Ask for `@alpha` explicitly so your lockfile records that you meant to.>
15
+ > **`alpha.15` is a breaking wire change, and it breaks daemons and relays —
16
+ > not app authors.** If you call `app.enqueue(...)` and read results, nothing
17
+ > in your code changes. If you run a daemon or an upstream, every package must
18
+ > move together: a mixed pair refuses on both sides, because both ends parse
19
+ > `.strict()`.
20
+ >
21
+ > What moved, all of it reconciling the frozen `byollm_009` with its code:
22
+ > `JobStub` gains `site` (the site's identity key id) and loses
23
+ > `audienceAllow`; `ResultRequest` gains `leaseId`; `HeartbeatResponse` loses
24
+ > `leases`, which nothing read; `WireErrorCode` gains `not-ready`,
25
+ > `clock-skew` and `forbidden`, and `403` is `forbidden` rather than
26
+ > `unauthorized`. `RESULT_PROVENANCE` is superseded by
27
+ > `PROVENANCE_NAMES_DEVICE`. See `byollm_009` Amendment A.>
28
+ > **`alpha.16` is a breaking wire change — daemons and relays again, not app
29
+ > authors.** `app.enqueue(...)` and reading results are unchanged. All five
30
+ > packages move together: both ends parse `.strict()`, so a mixed pair
31
+ > refuses.
32
+ >
33
+ > What moved, all of it Tier 2 of `cloud_008`: `model`, `backendClass` and
34
+ > `durationMs` come off `ResultRequest` and are sealed **inside** the result
35
+ > envelope as `SealedOutcome = { outcome, ran }` — so a daemon can no longer
36
+ > declare a model it did not sign, and a relay carries neither.
37
+ > `HeartbeatResponse` loses `leases` (nothing read it) and now reports real
38
+ > cancellations instead of an empty list. `WireErrorCode` gains `forbidden`
39
+ > for 403, leaving `unauthorized` at exactly 401. The relay gained a
40
+ > site-plane `cancel` endpoint, honours `stub.deadlineAt`, honours
41
+ > `stub.audience`, and remembers a refusal.>
42
+ > **`alpha.17` is additive** — no wire change. It exports `ReleaseReason`,
43
+ > which `RoutingStore.releaseLeases` names and the package did not export, so
44
+ > the interface was unimplementable outside this repo.>
45
+ > **`alpha.18` is a breaking wire change — daemons and relays, not app
46
+ > authors.** `app.enqueue(...)` and reading results are unchanged. All five
47
+ > packages move together.
48
+ >
49
+ > The **bearer token is gone**: off `PairPollResponse`, off the runner row,
50
+ > off the daemon's pairings file, out of the adapter's schema. It was minted,
51
+ > hashed and stored on two disks and never sent, looked up or compared —
52
+ > `REQUESTS_SIGNED_NOT_BEARER` was enforced by signatures the whole time. If
53
+ > you run the Supabase adapter, apply
54
+ > `20260819000000_drop_runner_token.sql`; `byollm_approve_pairing` now takes
55
+ > one argument. A pairings file written by an older daemon still loads.
56
+ >
57
+ > `model`, `backendClass` and `durationMs` moved **inside** the sealed result
58
+ > (`SealedOutcome = { outcome, ran }`), so a daemon cannot declare a model it
59
+ > did not sign and a relay carries none of them. Writing a `RoutingStore`?
60
+ > `releaseLeases` takes an optional `reason` and `complete` requires
61
+ > `leaseId`, and **an implementation that ignores either still typechecks** —
62
+ > run the store contract tests.>
63
+ > **`alpha.19` is additive on the wire and a behaviour change in every
64
+ > store.** `ResultResponse` gains an optional `duplicate`. Nothing is removed,
65
+ > so an older daemon keeps working — but the *order* two rules are checked in
66
+ > has changed, and a `RoutingStore` implementation must change with it.
67
+ >
68
+ > `complete` now checks **terminal state before holder**, scoped to the device
69
+ > that finished the job: a replay from that device is answered `duplicate:
70
+ > true` with a 2xx, and anyone else gets exactly the refusal they would get
71
+ > for a job that is not terminal. Previously `RESULT_IDEMPOTENT` held only
72
+ > because the lease is nulled on success, so the holder check tripped first —
73
+ > deleting the idempotency branch failed no test. Run the store contract
74
+ > tests; the compiler cannot see this.
75
+
76
+ <!-- release-note 0.1.0-alpha.21 -->
77
+ > [!NOTE]
78
+ > **`0.1.0-alpha.20` is not a complete release — do not pin it.** Four
79
+ > packages published and `@byollm/server` did not: a Sigstore
80
+ > transparency-log 409 on its provenance attestation. The workflow's
81
+ > "already published" guard correctly refuses to resume a partial publish,
82
+ > so `0.1.0-alpha.60` is that release, whole.
83
+ >
84
+ > If you run the Supabase adapter, `alpha.21` needs
85
+ > `20260819010000_completed_by_lease_id.sql`: alpha.19 shipped §3.6's
86
+ > ordering without the column it stores the grant in.
87
+
88
+ <!-- release-note 0.1.0-alpha.40 -->
89
+ **`byollm install` — stop keeping a terminal open.** The daemon can now run
90
+ under your computer's own supervisor and restart itself if it stops: a launchd
91
+ agent on macOS, a `systemd --user` unit on Linux, a logon task on Windows. All
92
+ user-level — no root, no system directories, and `byollm uninstall` takes it
93
+ away. `byollm status` gained a line saying whether it is actually supervised
94
+ right now, including the state that matters most: installed but not running,
95
+ which looks fine from an app's dashboard and serves nothing.
96
+
97
+ If you are running via `npx`, install properly first (`npm install -g
98
+ byollm@alpha`) — `install` refuses to supervise a copy in npx's cache, because
99
+ npm deletes that directory and the service would fail at some later boot.
100
+
101
+ <!-- release-note 0.1.0-alpha.41 -->
102
+ **`onNoRunner` takes a string.** Your fallback answer is your own value, not
103
+ wire data, and handing back a whole result record for it was ceremony — the
104
+ README's own example got the shape wrong, which is how this was found.
105
+
106
+ ```ts
107
+ const { outcome, fallback } = await job.result({
108
+ onNoRunner: () => runOnHostedModel(transcript),
109
+ });
110
+ ```
111
+
112
+ Whatever you return, `result()` labels it `fallback: true` — the stamp is
113
+ applied by the wait, not taken from you, so an answer that did not run on
114
+ somebody's device cannot be reported as though it did (`FALLBACK_LABELED`).
115
+ Both delivery channels do it, polling and Supabase Realtime. Records still
116
+ work; they just get labelled too.
15
117
 
16
118
  # `@byollm/conformance`
17
119
 
@@ -29,7 +131,7 @@ byollm conformance — my server
29
131
  ✓ C001_PAIRING_BINDS_ONE_USER a runner token is bound to exactly the approving user (279ms)
30
132
  ✓ C002_JOB_ROUND_TRIP an enqueued job runs on the owner's daemon and the result comes back (83ms)
31
133
 
32
- 16 checks passed — my server is byollm-compatible.
134
+ 32 checks passed — my server is byollm-compatible.
33
135
  ```
34
136
 
35
137
  ## What it actually does
@@ -79,7 +181,7 @@ Two optional hooks worth knowing about:
79
181
 
80
182
  - **`ownerId`** exists because owner ids are server-namespace-local. A target
81
183
  backed by real auth uses uuids, not names, and a kit that assumed names
82
- round-tripped would be assuming away the very thing the `named` allowlist is
184
+ round-tripped would be assuming away the very thing the `team` allowlist is
83
185
  about.
84
186
  - **`advanceTime`** lets an in-memory server run the lease and TTL checks in
85
187
  milliseconds. A real Postgres cannot fake its clock, so the kit waits for
@@ -95,7 +197,7 @@ Two optional hooks worth knowing about:
95
197
  | `C003_UNKNOWN_KIND_REFUSED` | a daemon is never handed a kind it did not advertise |
96
198
  | `C004_LEASE_RECLAIM` | a job whose runner vanished is offered again, losing nothing |
97
199
  | `C005_AUDIENCE_MATRIX` | all nine audience × offer-scope combinations |
98
- | `C006_NAMED_LOCAL_ALLOWLIST` | `named` runs only once the daemon's own list admits it |
200
+ | `C006_NAMED_LOCAL_ALLOWLIST` | `team` runs only once the daemon's own list admits it |
99
201
  | `C007_SUBSCRIPTION_SELF_LOCK` | a subscription backend refuses others' work at any scope |
100
202
  | `C008_REVOCATION` | a revoked daemon stops mid-queue |
101
203
  | `C009_CANCEL_MID_FLIGHT` | cancel aborts a running job's backend call |
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ auditDeployment,
4
+ formatPostureReport
5
+ } from "./chunk-4ML6G7NC.js";
6
+
7
+ // src/audit-cli.ts
8
+ var [url, basePath, originAddress] = process.argv.slice(2);
9
+ if (url === void 0) {
10
+ process.stderr.write(
11
+ "usage: byollm-audit-deployment <url> [base-path] [origin-address]\n e.g. byollm-audit-deployment https://hub.byollm.cloud\n"
12
+ );
13
+ process.exit(2);
14
+ }
15
+ var report = await auditDeployment({
16
+ url,
17
+ ...basePath === void 0 ? {} : { basePath },
18
+ // `D008` asks the origin directly. Without it that check says so rather
19
+ // than guessing an address and reporting a posture it never tested.
20
+ ...originAddress === void 0 ? {} : { originAddress }
21
+ });
22
+ process.stdout.write(`
23
+ ${formatPostureReport(report)}`);
24
+ process.exit(report.passed ? 0 : 1);
25
+ //# sourceMappingURL=audit-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/audit-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { auditDeployment, formatPostureReport } from \"./deployment.js\";\n\n/**\n * `byollm-audit-deployment <url>` — what a stranger can do to a running relay.\n *\n * Distinct from `byollm-certify`, which drives a real daemon against a target\n * that may be an in-process handler. This one has a URL and nothing else,\n * which is exactly what an attacker has, and it exists because eight\n * freeze-gate findings came from a suite in which nothing was ever a stranger.\n *\n * ```bash\n * npx byollm-audit-deployment https://hub.byollm.cloud\n * ```\n *\n * Safe to run against production: nothing writes, nothing floods, and every\n * request is one an ordinary scanner would make.\n */\nconst [url, basePath, originAddress] = process.argv.slice(2);\n\nif (url === undefined) {\n process.stderr.write(\n \"usage: byollm-audit-deployment <url> [base-path] [origin-address]\\n\" +\n \" e.g. byollm-audit-deployment https://hub.byollm.cloud\\n\",\n );\n process.exit(2);\n}\n\nconst report = await auditDeployment({\n url,\n ...(basePath === undefined ? {} : { basePath }),\n // `D008` asks the origin directly. Without it that check says so rather\n // than guessing an address and reporting a posture it never tested.\n ...(originAddress === undefined ? {} : { originAddress }),\n});\nprocess.stdout.write(`\\n${formatPostureReport(report)}`);\nprocess.exit(report.passed ? 0 : 1);\n"],"mappings":";;;;;;;AAkBA,IAAM,CAAC,KAAK,UAAU,aAAa,IAAI,QAAQ,KAAK,MAAM,CAAC;AAE3D,IAAI,QAAQ,QAAW;AACrB,UAAQ,OAAO;AAAA,IACb;AAAA,EAEF;AACA,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,MAAM,gBAAgB;AAAA,EACnC;AAAA,EACA,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;AAAA;AAAA;AAAA,EAG7C,GAAI,kBAAkB,SAAY,CAAC,IAAI,EAAE,cAAc;AACzD,CAAC;AACD,QAAQ,OAAO,MAAM;AAAA,EAAK,oBAAoB,MAAM,CAAC,EAAE;AACvD,QAAQ,KAAK,OAAO,SAAS,IAAI,CAAC;","names":[]}