@byollm/conformance 0.1.0-alpha.42 → 0.1.0-alpha.44

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.42`) — under active development. Don't use this yet.**
2
+ > **Alpha (`0.1.0-alpha.44`) — under active development. Don't use this yet.**
3
3
  >
4
4
  > Install it deliberately: `npm install @byollm/conformance@alpha`.
5
5
  >
@@ -79,7 +79,7 @@
79
79
  > packages published and `@byollm/server` did not: a Sigstore
80
80
  > transparency-log 409 on its provenance attestation. The workflow's
81
81
  > "already published" guard correctly refuses to resume a partial publish,
82
- > so `0.1.0-alpha.42` is that release, whole.
82
+ > so `0.1.0-alpha.44` is that release, whole.
83
83
  >
84
84
  > If you run the Supabase adapter, `alpha.21` needs
85
85
  > `20260819010000_completed_by_lease_id.sql`: alpha.19 shipped §3.6's
@@ -87,7 +87,7 @@
87
87
 
88
88
  <!-- release-note 0.1.0-alpha.40 -->
89
89
  **`byollm install` — stop keeping a terminal open.** The daemon can now run
90
- under your machine's own supervisor and restart itself if it stops: a launchd
90
+ under your computer's own supervisor and restart itself if it stops: a launchd
91
91
  agent on macOS, a `systemd --user` unit on Linux, a logon task on Windows. All
92
92
  user-level — no root, no system directories, and `byollm uninstall` takes it
93
93
  away. `byollm status` gained a line saying whether it is actually supervised
@@ -111,7 +111,7 @@ const { outcome, fallback } = await job.result({
111
111
 
112
112
  Whatever you return, `result()` labels it `fallback: true` — the stamp is
113
113
  applied by the wait, not taken from you, so an answer that did not run on
114
- somebody's machine cannot be reported as though it did (`FALLBACK_LABELED`).
114
+ somebody's device cannot be reported as though it did (`FALLBACK_LABELED`).
115
115
  Both delivery channels do it, polling and Supabase Realtime. Records still
116
116
  work; they just get labelled too.
117
117
 
@@ -181,7 +181,7 @@ Two optional hooks worth knowing about:
181
181
 
182
182
  - **`ownerId`** exists because owner ids are server-namespace-local. A target
183
183
  backed by real auth uses uuids, not names, and a kit that assumed names
184
- 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
185
185
  about.
186
186
  - **`advanceTime`** lets an in-memory server run the lease and TTL checks in
187
187
  milliseconds. A real Postgres cannot fake its clock, so the kit waits for
@@ -197,7 +197,7 @@ Two optional hooks worth knowing about:
197
197
  | `C003_UNKNOWN_KIND_REFUSED` | a daemon is never handed a kind it did not advertise |
198
198
  | `C004_LEASE_RECLAIM` | a job whose runner vanished is offered again, losing nothing |
199
199
  | `C005_AUDIENCE_MATRIX` | all nine audience × offer-scope combinations |
200
- | `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 |
201
201
  | `C007_SUBSCRIPTION_SELF_LOCK` | a subscription backend refuses others' work at any scope |
202
202
  | `C008_REVOCATION` | a revoked daemon stops mid-queue |
203
203
  | `C009_CANCEL_MID_FLIGHT` | cancel aborts a running job's backend call |
package/dist/audit-cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  auditDeployment,
4
4
  formatPostureReport
5
- } from "./chunk-JPFAPXWZ.js";
5
+ } from "./chunk-4ML6G7NC.js";
6
6
 
7
7
  // src/audit-cli.ts
8
8
  var [url, basePath, originAddress] = process.argv.slice(2);
@@ -11,7 +11,7 @@ var STUB = {
11
11
  id: "posture-probe",
12
12
  kind: "llm.generate",
13
13
  owner: "nobody",
14
- audience: "self",
14
+ audience: "private",
15
15
  sizeClass: "small",
16
16
  streaming: false,
17
17
  // Far enough out that a deployment cannot pass by calling it expired.
@@ -466,4 +466,4 @@ export {
466
466
  auditDeployment,
467
467
  formatPostureReport
468
468
  };
469
- //# sourceMappingURL=chunk-JPFAPXWZ.js.map
469
+ //# sourceMappingURL=chunk-4ML6G7NC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/deployment.ts"],"sourcesContent":["import { connect as tlsConnect } from \"node:tls\";\nimport { request as httpsRequest } from \"node:https\";\nimport {\n PROTOCOL_VERSION,\n generateKeys,\n signRequest,\n signSiteRequest,\n} from \"@byollm/protocol\";\n\n/**\n * The deployment posture audit — what an outsider can do to a running relay.\n *\n * ## Why this exists as a separate surface\n *\n * `certify` drives a real daemon against a {@link ConformanceTarget}, and a\n * target may be an in-process handler or an HTTP server: \"deliberately\n * transport-agnostic\", which is the right call for certifying a *protocol*.\n *\n * It is also a blind spot, and byollm_009's ninth finding lived in it. Eight\n * freeze-gate findings came from tests where the site reached the relay by\n * calling `handle()` on an object it held a reference to — and a harness that\n * invokes the system under test directly cannot see anything about how the\n * system is *reached*. The site plane had no authentication at all. Nothing\n * noticed, because nothing in the suite was ever a stranger.\n *\n * So this suite is a stranger. It holds no credential, no key the deployment\n * knows, and no reference to any object inside it. It has a URL, which is\n * exactly what an attacker has. Every check asks the question that form of\n * access makes available:\n *\n * - can I enqueue work into someone's machines?\n * - can I read who is online and what they are holding?\n * - can I make a signature that is *well-formed* and be believed?\n * - is anything served that should not be on the internet?\n * - can I reach a handler by dressing a path up to look like one?\n *\n * ## What this is not\n *\n * Not a penetration test, and not exhaustive — it cannot be, because the next\n * hole will be in whatever gets added next. It is the specific class that has\n * already bitten, turned into something that runs. That is the same move as\n * every other check in this kit: a finding becomes a check so its *shape*\n * cannot recur silently.\n *\n * It is also deliberately **safe to run against production**: nothing here\n * writes, nothing floods, and every request is one an ordinary scanner would\n * make. A posture audit you are nervous about running is one nobody runs.\n */\n\n/** One thing a stranger tried. */\nexport interface PostureCheck {\n /** Stable id, cited in output. */\n readonly id: string;\n /** What a person should understand from a failure. */\n readonly title: string;\n /** MUSTs this exercises, where one applies. Empty is honest, not a gap. */\n readonly cites: readonly string[];\n run(context: PostureContext): Promise<PostureOutcome>;\n}\n\nexport interface PostureContext {\n /** The origin, as an outsider would type it. */\n readonly origin: string;\n /** Where the daemon plane is mounted. */\n readonly basePath: string;\n /** Injectable, so a test can drive this without a network. */\n readonly fetch: typeof fetch;\n /**\n * The origin's own address, behind whatever edge fronts it — `D008`.\n *\n * Optional because most deployments have no separate origin, and a check\n * that guessed one would report a posture it never tested.\n */\n readonly originAddress?: string;\n}\n\nexport interface PostureOutcome {\n readonly passed: boolean;\n /** What actually happened, in a sentence someone can act on. */\n readonly detail: string;\n}\n\nexport interface PostureResult extends PostureOutcome {\n readonly id: string;\n readonly title: string;\n readonly cites: readonly string[];\n}\n\nexport interface PostureReport {\n readonly origin: string;\n readonly passed: boolean;\n readonly results: readonly PostureResult[];\n}\n\nconst STUB = {\n id: \"posture-probe\",\n kind: \"llm.generate\",\n owner: \"nobody\",\n audience: \"private\",\n sizeClass: \"small\",\n streaming: false,\n // Far enough out that a deployment cannot pass by calling it expired.\n deadlineAt: 4_102_444_800_000,\n};\n\n/** Refused, for any reason a server is entitled to refuse a stranger. */\nconst REFUSED = new Set([401, 403, 404]);\n\n/**\n * Refused **by a byollm relay**, rather than by nothing being there.\n *\n * The distinction is the whole difference between a posture audit and a\n * connectivity check, and this suite shipped without it for an hour. Running\n * against `hub.byollm.cloud` before its Ingress had a matching host rule, the\n * load balancer answered 404 to everything from its own error page — and the\n * audit reported 6/7, because 404 is a refusal and every probe got one.\n *\n * A completely dead deployment scored better than a working one. That is the\n * assertion-that-cannot-fail wearing its most convincing disguise: not a check\n * that never fails, but one that passes for a reason unrelated to the property\n * it claims.\n *\n * So a refusal has to be *byollm's* refusal: the protocol answers errors as\n * JSON with an `error` field, and Google's `backend NotFound` page does not.\n */\nasync function refusedByByollm(\n response: Response,\n): Promise<{ ok: boolean; why: string }> {\n if (!REFUSED.has(response.status)) {\n return { ok: false, why: `answered ${String(response.status)}` };\n }\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n return {\n ok: false,\n why:\n `answered ${String(response.status)} but not as byollm — ` +\n `something else is serving this path`,\n };\n }\n const shaped =\n typeof body === \"object\" &&\n body !== null &&\n typeof (body as { error?: unknown }).error === \"string\";\n return shaped\n ? { ok: true, why: `answered ${String(response.status)}` }\n : {\n ok: false,\n why:\n `answered ${String(response.status)} with a body byollm would not ` +\n `send — something else is serving this path`,\n };\n}\n\nconst outcome = (passed: boolean, detail: string): PostureOutcome => ({\n passed,\n detail,\n});\n\n/**\n * The certificate the **origin** serves, read off the connection.\n *\n * Connects to the origin's own address with the pinned hostname in SNI, which\n * is what an edge does when it validates. Certificate verification is off for\n * `D008`'s reason: the question is what this address presents, not whether to\n * trust it.\n *\n * **It must be the origin, not the hostname.** Written first as a plain\n * connection to `hub.byollm.cloud`, which goes *through* Cloudflare and\n * returns Cloudflare's own edge certificate — one that names the host by\n * construction and auto-renews on a ninety-day cycle. `D009` passed on it\n * while the origin's certificate named nothing relevant, which is the exact\n * condition finding 45 describes; `D010` then failed with \"84 days\" and\n * revealed that both were measuring the edge.\n *\n * Two certificates, two purposes: the edge one protects visitors and\n * Cloudflare renews it, and the origin one is what the edge validates and\n * nobody renews automatically. Only the second is this audit's business.\n */\nasync function servedCertificate(\n address: string,\n host: string,\n): Promise<{ names: readonly string[]; validTo: string } | undefined> {\n return new Promise((resolve) => {\n const socket = tlsConnect(\n {\n host: address,\n servername: host,\n port: 443,\n timeout: 15_000,\n rejectUnauthorized: false,\n },\n () => {\n const peer = socket.getPeerCertificate();\n const alt = (peer.subjectaltname ?? \"\")\n .split(\",\")\n .map((entry) => entry.trim().replace(/^DNS:/, \"\"))\n .filter((entry) => entry.length > 0);\n const cn: unknown = peer.subject.CN;\n socket.end();\n resolve({\n names: alt.length > 0 ? alt : [typeof cn === \"string\" ? cn : \"\"],\n validTo: peer.valid_to,\n });\n },\n );\n socket.on(\"error\", () => {\n resolve(undefined);\n });\n socket.on(\"timeout\", () => {\n socket.destroy();\n resolve(undefined);\n });\n });\n}\n\nexport const POSTURE_CHECKS: readonly PostureCheck[] = Object.freeze([\n {\n id: \"D001_SITE_ENQUEUE_REFUSES_UNSIGNED\",\n title: \"an anonymous caller cannot enqueue work in a site's name\",\n cites: [\"REQUESTS_SIGNED_NOT_BEARER\"],\n async run({ origin, fetch: f }) {\n const response = await f(`${origin}/relay/site/enqueue`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n // The version, because the auditor is a site-plane client like any\n // other (§B.4). Without it the relay refuses on the handshake and\n // this check would report \"refused\" for a reason that has nothing to\n // do with signatures — success for an unrelated reason, which is the\n // failure this whole file was written against.\n body: JSON.stringify({\n protocolVersion: PROTOCOL_VERSION,\n siteId: \"any-site\",\n stub: STUB,\n }),\n });\n // The finding, exactly: a relay that accepts this routes unsolicited\n // work to consenting users' private hardware. The payload that follows\n // is sealed by the real site or not at all, so nothing forged *runs* —\n // and dispatch to someone's machine is a breach whatever the\n // ciphertext does.\n const refusal = await refusedByByollm(response);\n return outcome(refusal.ok, `POST /relay/site/enqueue ${refusal.why}`);\n },\n },\n {\n id: \"D002_SITE_READS_REFUSE_UNSIGNED\",\n title: \"an anonymous caller cannot read who is online\",\n cites: [\"REQUESTS_SIGNED_NOT_BEARER\"],\n async run({ origin, fetch: f }) {\n // Reads matter as much as writes here. A blind relay's whole claim is\n // that it holds routing metadata and nothing else — which makes that\n // metadata the entire prize, and \"who is online right now, on which\n // device, holding which lease\" is the shape of it.\n const why: string[] = [];\n let ok = true;\n for (const path of [\"pending\", \"results\"]) {\n const response = await f(\n `${origin}/relay/site/${path}?siteId=any-site&protocolVersion=${PROTOCOL_VERSION}`,\n );\n const refusal = await refusedByByollm(response);\n ok &&= refusal.ok;\n why.push(`${path} ${refusal.why}`);\n }\n return outcome(ok, why.join(\"; \"));\n },\n },\n {\n id: \"D003_DAEMON_PLANE_REFUSES_UNSIGNED\",\n title: \"an anonymous caller cannot claim work\",\n cites: [\"REQUESTS_SIGNED_NOT_BEARER\", \"CLAIM_REQUIRES_CAPABILITY\"],\n async run({ origin, basePath, fetch: f }) {\n const response = await f(`${origin}${basePath}/claim`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n protocolVersion: \"0\",\n runnerId: \"nobody\",\n max: 1,\n capabilities: [{ kind: \"llm.generate\", models: [\"any\"] }],\n }),\n });\n const refusal = await refusedByByollm(response);\n return outcome(refusal.ok, `POST ${basePath}/claim ${refusal.why}`);\n },\n },\n {\n id: \"D004_REFUSES_A_STRANGER_S_VALID_SIGNATURE\",\n title: \"a well-formed signature from an unknown key is not enough\",\n cites: [\"REQUESTS_SIGNED_NOT_BEARER\", \"KEYS_EXCHANGED_AT_CONSENT\"],\n async run({ origin, basePath, fetch: f }) {\n // The check `D001`–`D003` cannot make: everything about these requests\n // is correct except whose key signed them. A deployment that verified\n // signatures without checking *whose* would pass the three above and\n // fail here, and that is a real implementation mistake rather than a\n // hypothetical one — verifying a signature and identifying a signer are\n // two steps, and the second is the one that gets skipped.\n const stranger = generateKeys(Date.now());\n const now = Date.now();\n\n const siteBody = JSON.stringify({\n protocolVersion: PROTOCOL_VERSION,\n siteId: \"any-site\",\n stub: STUB,\n });\n const siteSignature = signSiteRequest(stranger, {\n endpoint: \"enqueue\",\n siteId: \"any-site\",\n issuedAt: now,\n body: siteBody,\n });\n const site = await f(`${origin}/relay/site/enqueue`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-byollm-site\": \"any-site\",\n \"x-byollm-issued-at\": String(siteSignature.issuedAt),\n \"x-byollm-signature\": siteSignature.signature,\n },\n body: siteBody,\n });\n\n const daemonBody = JSON.stringify({\n protocolVersion: \"0\",\n runnerId: \"nobody\",\n max: 1,\n capabilities: [{ kind: \"llm.generate\", models: [\"any\"] }],\n });\n const daemonSignature = signRequest(stranger, {\n endpoint: \"claim\",\n runnerId: \"nobody\",\n issuedAt: now,\n body: daemonBody,\n });\n const daemon = await f(`${origin}${basePath}/claim`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-byollm-runner\": \"nobody\",\n \"x-byollm-issued-at\": String(daemonSignature.issuedAt),\n \"x-byollm-signature\": daemonSignature.signature,\n },\n body: daemonBody,\n });\n\n const siteRefusal = await refusedByByollm(site);\n const daemonRefusal = await refusedByByollm(daemon);\n return outcome(\n siteRefusal.ok && daemonRefusal.ok,\n `signed by a stranger: site ${siteRefusal.why}, daemon ${daemonRefusal.why}`,\n );\n },\n },\n {\n id: \"D011_VERSION_NAMED_ON_BOTH_PLANES\",\n title: \"an unknown protocol version is refused by name, not by accident\",\n cites: [\"VERSION_HANDSHAKE_REQUIRED\"],\n async run({ origin, fetch: f }) {\n // byollm_009 §B.4. A mismatch that arrives as a generic `bad-request`\n // leaves a daemon and a server to discover they disagree by failing,\n // with nothing in the answer naming the disagreement or the fix — which\n // is what this relay did on every endpoint until the handshake landed.\n //\n // **Both planes, because the gap was a whole plane.** The daemon plane\n // had version literals in its schemas and the site plane had none, so a\n // check that probed one would have reported a handshake the other did\n // not have.\n const probes: { where: string; response: Response }[] = [\n {\n where: \"daemon\",\n response: await f(`${origin}/byollm/claim`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ protocolVersion: \"99\", max: 1 }),\n }),\n },\n {\n where: \"site\",\n response: await f(`${origin}/relay/site/enqueue`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n protocolVersion: \"99\",\n siteId: \"any-site\",\n stub: STUB,\n }),\n }),\n },\n ];\n\n const wrong: string[] = [];\n for (const probe of probes) {\n let body: { error?: string; supported?: unknown } = {};\n try {\n body = (await probe.response.json()) as typeof body;\n } catch {\n wrong.push(\n `${probe.where}: answered ${String(probe.response.status)} and not as byollm`,\n );\n continue;\n }\n if (body.error !== \"unsupported-protocol-version\") {\n wrong.push(\n `${probe.where}: answered ${String(probe.response.status)} ${String(body.error)}`,\n );\n continue;\n }\n // Named, not merely refused: the field a client acts on.\n if (!Array.isArray(body.supported)) {\n wrong.push(`${probe.where}: refused without naming what it speaks`);\n }\n }\n\n return outcome(\n wrong.length === 0,\n wrong.length === 0\n ? \"both planes name the version they speak\"\n : wrong.join(\"; \"),\n );\n },\n },\n\n {\n id: \"D005_NO_DEBUG_SURFACE\",\n title: \"the debug page is not on the internet\",\n cites: [],\n async run({ origin, basePath, fetch: f }) {\n // Finding eleven. The relay's debug page shows no prompt or result text\n // — it does not have them — and it does show every routed job, who\n // claimed it, and every lease in flight. Closing the site plane while\n // leaving this open protects the data from one door and not the other.\n const paths = [\"/debug\", `${basePath}/debug`];\n const statuses: number[] = [];\n for (const path of paths) {\n const response = await f(`${origin}${path}`);\n statuses.push(response.status);\n }\n return outcome(\n // **Not merely \"not 200\"** — cloud_009 §3 made the page per-site, so\n // an enabled one answers a probe with no site id `400` rather than\n // rendering. A check that accepted anything but 200 would pass\n // against a deployment whose debug page is one query parameter away,\n // which is finding eleven with a shorter walk.\n //\n // `404` is the only answer that means the route does not exist. The\n // reference relay says exactly that when its debug page is off, and\n // says `400` when it is on and the caller named no site.\n statuses.every((status) => status === 404),\n `debug paths answered ${statuses.map(String).join(\"/\")}`,\n );\n },\n },\n {\n id: \"D006_NO_PATH_DISPATCH\",\n title: \"a handler cannot be reached by dressing a path up to look like it\",\n cites: [\"REQUESTS_SIGNED_NOT_BEARER\"],\n async run({ origin, fetch: f }) {\n // A router that dispatched on the last path segment would serve\n // `/literally/anything/claim`. Worth checking from outside because it\n // is invisible from inside: an in-process harness calls the handler by\n // name and never constructs a URL that could be misread.\n const response = await f(`${origin}/literally/anything/claim`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ protocolVersion: \"0\", max: 1 }),\n });\n const refusal = await refusedByByollm(response);\n return outcome(\n refusal.ok && response.status === 404,\n `POST /literally/anything/claim ${refusal.why}`,\n );\n },\n },\n {\n id: \"D007_TLS_ONLY\",\n title: \"the deployment is reached over TLS, and plaintext is not served\",\n cites: [],\n async run({ origin, fetch: f }) {\n if (!origin.startsWith(\"https://\")) {\n // Not a failure when auditing a local hub on purpose, but never\n // silent: an audit that reports \"posture good\" against an http origin\n // has certified the one thing that matters least.\n return outcome(false, `origin is ${origin} — this audit saw no TLS`);\n }\n // Payloads are sealed end to end and would survive plaintext transport.\n // Request signatures would not: on the wire they are replayable by\n // anyone on the path for the length of the freshness window, and every\n // site-plane and daemon-plane call carries one.\n const plain = origin.replace(\"https://\", \"http://\");\n const response = await f(`${plain}/healthz`, { redirect: \"manual\" });\n const redirected =\n response.status >= 300 &&\n response.status < 400 &&\n (response.headers.get(\"location\") ?? \"\").startsWith(\"https://\");\n return outcome(\n redirected || REFUSED.has(response.status),\n `plaintext answered ${String(response.status)}${\n redirected ? \" and redirects to https\" : \"\"\n }`,\n );\n },\n },\n\n {\n id: \"D008_ORIGIN_NOT_PUBLIC\",\n title: \"the origin answers the edge, and nobody else\",\n cites: [],\n async run({ origin, originAddress }) {\n // cloud_008 findings 44/45. A load balancer has a public address, and\n // an edge in front of it is a convention rather than a boundary until\n // the origin refuses everything else: anyone who resolves the address\n // reaches the hub past every WAF rule, rate limit and bot check the\n // zone applies, and appears in no edge log doing it.\n //\n // Bounded, and not nothing. Requests are signed and payloads sealed, so\n // a stranger cannot forge a claim or read a job — but they can reach\n // `/byollm/pair` and every plane endpoint at whatever rate the origin\n // serves, which is exactly the surface the edge exists to absorb.\n //\n // Skipped rather than failed when no address is supplied: an auditor\n // who does not know where the origin lives cannot ask this, and\n // guessing would be a check that passes for not looking.\n if (originAddress === undefined) {\n // **Fails, not skips.** This file's own rule, and the suite already\n // had a test for it: an audit that drops a check it could not run\n // reports a posture nobody measured, which reads identically to one\n // measured and found good.\n //\n // Written as a pass first, on the reasoning that most deployments\n // have no separate origin — and that test failed it immediately. The\n // reasoning was wrong in the way this whole audit exists to catch:\n // \"probably fine\" and \"verified\" must not print the same.\n return outcome(\n false,\n \"no origin address given — this posture was not measured \" +\n \"(pass the origin's address as the third argument)\",\n );\n }\n\n // Asked the way an attacker would, which `fetch` cannot.\n //\n // The first version of this check used `fetch` and passed for the wrong\n // reason: TLS fails against a bare IP because the certificate does not\n // name it, the request never reaches the load balancer's backend, and a\n // connection error read as \"refused\". It would have reported a green\n // origin with no policy attached at all.\n //\n // Plain HTTP does not work either — the frontend answers `301` before\n // any backend is chosen, so the policy is never consulted.\n //\n // So: HTTPS to the address, with the real host in SNI, and certificate\n // verification **off**. That is not a lapse. The property under test is\n // whether an address answers a stranger, not who the answer comes from,\n // and refusing to look because the certificate does not match the IP is\n // how the first version passed while proving nothing. Nothing else in\n // this kit may copy it.\n const host = new URL(origin).host;\n const status = await new Promise<number | \"refused\">((resolve) => {\n const request = httpsRequest(\n {\n host: originAddress,\n servername: host,\n headers: { host },\n path: \"/readyz\",\n method: \"GET\",\n rejectUnauthorized: false,\n timeout: 15_000,\n },\n (response) => {\n response.resume();\n resolve(response.statusCode ?? 0);\n },\n );\n request.on(\"error\", () => {\n resolve(\"refused\");\n });\n request.on(\"timeout\", () => {\n request.destroy();\n resolve(\"refused\");\n });\n request.end();\n });\n\n if (status === \"refused\") {\n // Nothing answered at all, which is the strongest form of this.\n return outcome(true, \"the origin address refused the connection\");\n }\n return outcome(\n status === 403,\n `the origin answered ${String(status)} to a direct request`,\n );\n },\n },\n\n {\n id: \"D009_CERT_NAMES_THE_PINNED_HOST\",\n title: \"the certificate names the hostname daemons pin\",\n cites: [],\n async run({ origin, originAddress }) {\n // cloud_008 finding 45. The load balancer held one certificate, for the\n // *origin* hostname, and `hub.byollm.cloud` — the name every daemon\n // pins and the edge validates — was not on it. Cloudflare cannot verify\n // a certificate that does not name what it asked for, so the zone sat\n // on plain Full: encrypted to the origin, not checking who the origin\n // is, while every daemon's pinned site keys arrive through it.\n //\n // Nothing said so. \"There is a certificate\" and \"there is a certificate\n // for the name being validated\" printed identically, which is why this\n // check exists rather than a note in a runbook.\n //\n // Asked over TLS with the real SNI and read from the peer, so it is the\n // certificate actually served rather than one somebody configured.\n const host = new URL(origin).host;\n if (originAddress === undefined) {\n return outcome(\n false,\n \"no origin address given — this posture was not measured. \" +\n \"Asking the hostname reads the edge's certificate, which names it \" +\n \"by construction and proves nothing about the origin\",\n );\n }\n const served = await servedCertificate(originAddress, host);\n const names = served?.names;\n\n if (names === undefined) {\n return outcome(\n false,\n `could not read a certificate from ${originAddress}`,\n );\n }\n const covered = names.some(\n (name) =>\n name === host ||\n (name.startsWith(\"*.\") && host.endsWith(name.slice(1))),\n );\n return outcome(\n covered,\n covered\n ? `served a certificate naming ${host}`\n : `the certificate names ${names.join(\", \")} — not ${host}`,\n );\n },\n },\n\n {\n id: \"D010_CERT_HAS_LIFE_LEFT\",\n title: \"the certificate is not about to expire\",\n cites: [],\n async run({ origin, originAddress }) {\n // A long-lived certificate is the kind whose expiry gets written in a\n // note and never looked at again. The one this deployment now depends\n // on runs to 2041, which makes it *more* likely to be forgotten, not\n // less — and it is load-bearing: it is what the edge validates before\n // it will carry a daemon's traffic at all.\n //\n // Measured from the artefact rather than from the note. A date somebody\n // owns has to mean a date something checks.\n //\n // Ninety days: long enough that a renewal is scheduled rather than\n // scrambled, short enough that the warning is still about something\n // real.\n const host = new URL(origin).host;\n if (originAddress === undefined) {\n return outcome(\n false,\n \"no origin address given — this posture was not measured \" +\n \"(the edge's certificate is Cloudflare's to renew, not ours)\",\n );\n }\n const served = await servedCertificate(originAddress, host);\n if (served === undefined) {\n return outcome(\n false,\n `could not read a certificate from ${originAddress}`,\n );\n }\n const days = Math.round(\n (Date.parse(served.validTo) - Date.now()) / 86_400_000,\n );\n return outcome(\n days > 90,\n `the certificate expires ${served.validTo} (${String(days)} days)`,\n );\n },\n },\n]);\n\n/**\n * Audit a running deployment. Holds nothing it was not given a URL for.\n *\n * Every check runs even after one fails, because a posture report's job is to\n * be a complete picture rather than the first thing that went wrong.\n */\nexport async function auditDeployment(options: {\n url: string;\n basePath?: string;\n /** The origin behind the edge, for `D008`. */\n originAddress?: string;\n fetch?: typeof fetch;\n onProgress?: (result: PostureResult) => void;\n}): Promise<PostureReport> {\n const origin = options.url.replace(/\\/+$/, \"\");\n const context: PostureContext = {\n origin,\n basePath: (options.basePath ?? \"/byollm\").replace(/\\/+$/, \"\"),\n ...(options.originAddress === undefined\n ? {}\n : { originAddress: options.originAddress }),\n fetch: options.fetch ?? globalThis.fetch,\n };\n\n const results: PostureResult[] = [];\n for (const check of POSTURE_CHECKS) {\n let result: PostureResult;\n try {\n result = { ...(await check.run(context)), ...describe(check) };\n } catch (error) {\n // A check that cannot complete is a failure, not a skip. An audit that\n // silently drops a probe it could not run reports a posture nobody\n // measured — which is worse than reporting none at all.\n result = {\n ...describe(check),\n passed: false,\n detail: `the probe failed: ${error instanceof Error ? error.message : \"unknown\"}`,\n };\n }\n results.push(result);\n options.onProgress?.(result);\n }\n\n return {\n origin,\n passed: results.every((result) => result.passed),\n results,\n };\n}\n\nconst describe = (check: PostureCheck) => ({\n id: check.id,\n title: check.title,\n cites: check.cites,\n});\n\nexport function formatPostureReport(report: PostureReport): string {\n const lines = [`deployment posture — ${report.origin}`, \"\"];\n for (const result of report.results) {\n lines.push(` ${result.passed ? \"ok \" : \"FAIL\"} ${result.id}`);\n lines.push(` ${result.title}`);\n lines.push(` ${result.detail}`);\n if (result.cites.length > 0) {\n lines.push(` cites ${result.cites.join(\", \")}`);\n }\n }\n const passed = report.results.filter((result) => result.passed).length;\n lines.push(\n \"\",\n report.passed\n ? `${String(passed)}/${String(report.results.length)} — a stranger got nowhere.`\n : `${String(passed)}/${String(report.results.length)} — a stranger got somewhere. See FAIL above.`,\n \"\",\n );\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
@@ -94,9 +94,11 @@ function daemonConfig(options) {
94
94
  const baseUrl = metered ? metered.baseUrl : options.subscription ? void 0 : "http://127.0.0.1:11434/v1";
95
95
  return resolveConfig(
96
96
  DaemonConfig.parse({
97
- backends: {
97
+ services: {
98
98
  primary: {
99
- backend: backendId,
99
+ model: "echo-model",
100
+ kinds: ["llm.generate", "llm.chat"],
101
+ type: backendId,
100
102
  ...baseUrl === void 0 ? {} : { baseUrl },
101
103
  offer: options.offer,
102
104
  ...metered === void 0 ? {} : {
@@ -107,10 +109,6 @@ function daemonConfig(options) {
107
109
  }
108
110
  }
109
111
  },
110
- routes: {
111
- "llm.generate": { backend: "primary", model: "echo-model" },
112
- "llm.chat": { backend: "primary", model: "echo-model" }
113
- },
114
112
  concurrency: 4
115
113
  })
116
114
  );
@@ -118,7 +116,7 @@ function daemonConfig(options) {
118
116
  async function pairDaemon(target, options) {
119
117
  const home = await mkdtemp(join(tmpdir(), "byollm-conformance-"));
120
118
  const loaded = daemonConfig({
121
- offer: options.offer ?? "self",
119
+ offer: options.offer ?? "private",
122
120
  subscription: options.subscription ?? false,
123
121
  ...options.metered === void 0 ? {} : { metered: options.metered }
124
122
  });
@@ -140,6 +138,8 @@ async function pairDaemon(target, options) {
140
138
  const fetchImpl = (input, init) => target.fetch(new Request(input, init));
141
139
  const capabilities = loaded.routes.map((route) => ({
142
140
  kind: route.kind,
141
+ service: route.service,
142
+ isDefault: true,
143
143
  backendId: route.backendId,
144
144
  backendClass: route.backendClass,
145
145
  model: route.model,
@@ -479,7 +479,7 @@ async function fetchGenuine(target, daemon, owner = "alice") {
479
479
  // The target's own name for the user, not the id it mapped that to —
480
480
  // passing a mapped id back in addresses a user the target never made.
481
481
  owner,
482
- audience: "self"
482
+ audience: "private"
483
483
  });
484
484
  for (let attempt = 0; attempt < 20; attempt += 1) {
485
485
  try {
@@ -525,7 +525,7 @@ var CHECKS = [
525
525
  kind: "llm.generate",
526
526
  payload: prompt("alice's private prompt"),
527
527
  owner: "alice",
528
- audience: "self"
528
+ audience: "private"
529
529
  });
530
530
  await bob.runner.tick();
531
531
  await sleep(50);
@@ -604,10 +604,12 @@ var CHECKS = [
604
604
  const generateOnly = await claimRaw(target, daemon, [
605
605
  {
606
606
  kind: "llm.generate",
607
+ service: "local",
608
+ isDefault: true,
607
609
  backendId: "openai-http",
608
610
  backendClass: "http",
609
611
  model: "echo-model",
610
- offerScope: "self"
612
+ offerScope: "private"
611
613
  }
612
614
  ]);
613
615
  assert(
@@ -692,15 +694,15 @@ var CHECKS = [
692
694
  musts: ["AUDIENCE_BOTH_SIDES", "NAMED_LOCAL_ALLOWLIST"],
693
695
  async run(target) {
694
696
  const expected = {
695
- "self:self": false,
696
- "self:named": false,
697
- "self:public": false,
698
- "named:self": false,
699
- "named:named": false,
697
+ "private:private": false,
698
+ "private:team": false,
699
+ "private:public": false,
700
+ "team:private": false,
701
+ "team:team": false,
700
702
  // refused locally — allowlist is empty
701
- "named:public": true,
702
- "public:self": false,
703
- "public:named": false,
703
+ "team:public": true,
704
+ "public:private": false,
705
+ "public:team": false,
704
706
  // refused locally — allowlist is empty
705
707
  "public:public": true
706
708
  };
@@ -736,13 +738,13 @@ var CHECKS = [
736
738
  title: "a named job runs only once the daemon's own allowlist admits it",
737
739
  musts: ["NAMED_LOCAL_ALLOWLIST", "REFUSAL_NOT_REOFFERED"],
738
740
  async run(target) {
739
- const bob = await pairDaemon(target, { owner: "bob", offer: "named" });
741
+ const bob = await pairDaemon(target, { owner: "bob", offer: "team" });
740
742
  try {
741
743
  const refused = await target.enqueue({
742
744
  kind: "llm.generate",
743
745
  payload: prompt("before"),
744
746
  owner: "alice",
745
- audience: "named"
747
+ audience: "team"
746
748
  });
747
749
  await bob.runner.tick();
748
750
  await sleep(80);
@@ -763,7 +765,7 @@ var CHECKS = [
763
765
  kind: "llm.generate",
764
766
  payload: prompt("after"),
765
767
  owner: "alice",
766
- audience: "named"
768
+ audience: "team"
767
769
  });
768
770
  await bob.runner.tick();
769
771
  await waitFor(
@@ -811,7 +813,7 @@ var CHECKS = [
811
813
  kind: "llm.generate",
812
814
  payload: prompt("my own work"),
813
815
  owner: "bob",
814
- audience: "self"
816
+ audience: "private"
815
817
  });
816
818
  await bob.runner.tick();
817
819
  await waitFor(async () => (await target.job(own.id))?.state === "ok", {
@@ -966,13 +968,13 @@ var CHECKS = [
966
968
  kind: "llm.generate",
967
969
  payload: prompt("step one"),
968
970
  owner: "bob",
969
- audience: "self"
971
+ audience: "private"
970
972
  });
971
973
  const second = await target.enqueue({
972
974
  kind: "llm.generate",
973
975
  payload: prompt("step two"),
974
976
  owner: "alice",
975
- audience: "self",
977
+ audience: "private",
976
978
  dependsOn: [first.id]
977
979
  });
978
980
  await alice.runner.tick();
@@ -1095,7 +1097,7 @@ var CHECKS = [
1095
1097
  kind: "llm.generate",
1096
1098
  payload: prompt("my own"),
1097
1099
  owner: "bob",
1098
- audience: "self"
1100
+ audience: "private"
1099
1101
  });
1100
1102
  await bob.runner.tick();
1101
1103
  await waitFor(async () => (await target.job(own.id))?.state === "ok", {
@@ -1198,7 +1200,7 @@ var CHECKS = [
1198
1200
  });
1199
1201
  try {
1200
1202
  assert(
1201
- bob.loaded.routes.every((route) => route.offerScope === "self"),
1203
+ bob.loaded.routes.every((route) => route.offerScope === "private"),
1202
1204
  "a metered backend was advertised beyond its owner without consent"
1203
1205
  );
1204
1206
  assert(
@@ -1239,7 +1241,7 @@ var CHECKS = [
1239
1241
  kind: "llm.generate",
1240
1242
  payload: prompt("my own work"),
1241
1243
  owner: "bob",
1242
- audience: "self"
1244
+ audience: "private"
1243
1245
  });
1244
1246
  await bob.runner.tick();
1245
1247
  await waitFor(async () => (await target.job(own.id))?.state === "ok", {
@@ -1315,7 +1317,7 @@ var CHECKS = [
1315
1317
  kind: "llm.generate",
1316
1318
  payload: prompt("my own work, my own key"),
1317
1319
  owner: "bob",
1318
- audience: "self"
1320
+ audience: "private"
1319
1321
  });
1320
1322
  await bob.runner.tick();
1321
1323
  await waitFor(async () => (await target.job(own.id))?.state === "ok", {
@@ -1338,7 +1340,7 @@ var CHECKS = [
1338
1340
  kind: "llm.generate",
1339
1341
  payload: prompt("only once, please"),
1340
1342
  owner: "alice",
1341
- audience: "self"
1343
+ audience: "private"
1342
1344
  });
1343
1345
  await Promise.all([a.runner.tick(), b.runner.tick()]);
1344
1346
  await waitFor(async () => (await target.job(job.id))?.state === "ok", {
@@ -1466,7 +1468,7 @@ var CHECKS = [
1466
1468
  baseUrl: "http://evil.test/v1"
1467
1469
  },
1468
1470
  owner: "alice",
1469
- audience: "self"
1471
+ audience: "private"
1470
1472
  });
1471
1473
  } catch {
1472
1474
  refused = true;
@@ -1496,7 +1498,7 @@ var CHECKS = [
1496
1498
  kind: "llm.generate",
1497
1499
  payload: prompt("ordinary text"),
1498
1500
  owner: "alice",
1499
- audience: "self"
1501
+ audience: "private"
1500
1502
  });
1501
1503
  await daemon.runner.tick();
1502
1504
  await waitFor(async () => (await target.job(ok.id))?.state === "ok", {
@@ -1714,7 +1716,7 @@ var CHECKS = [
1714
1716
  kind: "llm.generate",
1715
1717
  payload: prompt("run me once"),
1716
1718
  owner: "alice",
1717
- audience: "self"
1719
+ audience: "private"
1718
1720
  });
1719
1721
  const first = await claimOne(target, daemon);
1720
1722
  assert(
@@ -1754,7 +1756,7 @@ var CHECKS = [
1754
1756
  kind: "llm.generate",
1755
1757
  payload: prompt("this must not appear in a claim response"),
1756
1758
  owner: "alice",
1757
- audience: "self"
1759
+ audience: "private"
1758
1760
  });
1759
1761
  const stub = await claimOne(target, daemon);
1760
1762
  const asRecord = stub;
@@ -1819,7 +1821,7 @@ var CHECKS = [
1819
1821
  kind: "llm.generate",
1820
1822
  payload: prompt(secret),
1821
1823
  owner: "alice",
1822
- audience: "self"
1824
+ audience: "private"
1823
1825
  });
1824
1826
  const stored = await target.job(job.id);
1825
1827
  assert(
@@ -1968,7 +1970,7 @@ var CHECKS = [
1968
1970
  kind: "llm.generate",
1969
1971
  payload: prompt("alice's own machines only"),
1970
1972
  owner: "alice",
1971
- audience: "self"
1973
+ audience: "private"
1972
1974
  });
1973
1975
  const offered = await claimRaw(target, bob);
1974
1976
  assert(
@@ -2002,7 +2004,7 @@ var CHECKS = [
2002
2004
  kind: "llm.generate",
2003
2005
  payload: prompt("who else is on this roster"),
2004
2006
  owner: "alice",
2005
- audience: "named",
2007
+ audience: "team",
2006
2008
  // The site restricts the job to people who are not this daemon's
2007
2009
  // owner. A stub that carried the list would be handing a routing
2008
2010
  // party the membership of alice's group.
@@ -2031,7 +2033,7 @@ var CHECKS = [
2031
2033
  );
2032
2034
  }
2033
2035
  assert(
2034
- claimed.audience === "named",
2036
+ claimed.audience === "team",
2035
2037
  "the stub lost the audience routing decides on"
2036
2038
  );
2037
2039
  assert(
@@ -2148,4 +2150,4 @@ export {
2148
2150
  miscoveredMusts,
2149
2151
  formatReport
2150
2152
  };
2151
- //# sourceMappingURL=chunk-SWXTCMPN.js.map
2153
+ //# sourceMappingURL=chunk-FCX5R4LZ.js.map