@byollm/relay 0.1.0-alpha.44 → 0.1.0-alpha.46
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 +4 -4
- package/dist/{chunk-HQDS3K5W.js → chunk-XLWNHHLS.js} +7 -2
- package/dist/chunk-XLWNHHLS.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +35 -8
- package/dist/index.js.map +1 -1
- package/dist/{store-BVvGc3ca.d.ts → store-C7jG6b9m.d.ts} +40 -1
- package/dist/store-contract.d.ts +1 -1
- package/dist/store-contract.js +158 -11
- package/dist/store-contract.js.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-HQDS3K5W.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PublicIdentity, CapabilityMatrix, JobStub, SealedEnvelope, ClaimedStub } from '@byollm/protocol';
|
|
1
|
+
import { PublicIdentity, CapabilityMatrix, WithheldKind, JobStub, SealedEnvelope, ClaimedStub } from '@byollm/protocol';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The relay's routing state — byollm_009 §7, reachable at last.
|
|
@@ -129,6 +129,21 @@ interface Presence {
|
|
|
129
129
|
* exists to make visible rather than refuse.
|
|
130
130
|
*/
|
|
131
131
|
capabilities: CapabilityMatrix;
|
|
132
|
+
/**
|
|
133
|
+
* Kinds this machine is deliberately *not* advertising — byollm_016.
|
|
134
|
+
*
|
|
135
|
+
* Presence data for the same reason capabilities are, and stored beside
|
|
136
|
+
* them rather than derived: two services answering one kind with no
|
|
137
|
+
* `defaults` entry is a state only the daemon can see, and the hub cannot
|
|
138
|
+
* reconstruct it from the matrix — an absent kind and a withheld kind look
|
|
139
|
+
* identical there. Without this field the owner's page can say "nothing
|
|
140
|
+
* serves llm.generate", which is true and useless, instead of "two services
|
|
141
|
+
* answer it and you have not chosen", which is the sentence that ends with
|
|
142
|
+
* the owner doing something.
|
|
143
|
+
*
|
|
144
|
+
* Empty is the normal answer, and means every kind resolved.
|
|
145
|
+
*/
|
|
146
|
+
withheld: readonly WithheldKind[];
|
|
132
147
|
}
|
|
133
148
|
/**
|
|
134
149
|
* What a routing store must do, expressed as operations — cloud_006 §3.2.
|
|
@@ -177,7 +192,31 @@ interface ClaimInput {
|
|
|
177
192
|
* cannot travel to a store over a network, and a set can.
|
|
178
193
|
*/
|
|
179
194
|
readonly routes: ReadonlySet<string>;
|
|
195
|
+
/**
|
|
196
|
+
* Kinds this device has a **default** for, which is what serves an
|
|
197
|
+
* unselected job.
|
|
198
|
+
*
|
|
199
|
+
* Not "kinds it can run": since byollm_016 a device may advertise several
|
|
200
|
+
* services answering one kind, and a job that named none of them must go to
|
|
201
|
+
* the one its owner chose. A kind with two claimants and no default is
|
|
202
|
+
* withheld and does not appear here at all.
|
|
203
|
+
*/
|
|
180
204
|
readonly kinds: ReadonlySet<string>;
|
|
205
|
+
/**
|
|
206
|
+
* The (kind, service) pairs this device advertises — byollm_016 Phase B.
|
|
207
|
+
*
|
|
208
|
+
* **One set of pairs, for the reason `routes` above is one set of pairs.**
|
|
209
|
+
* A set of kinds and a set of service names would multiply: a device
|
|
210
|
+
* offering `studio` for `llm.generate` and `claude` for `llm.chat` has both
|
|
211
|
+
* kinds and both names, and the product contains
|
|
212
|
+
* (`llm.chat`, `studio`) — a combination it never advertised and cannot
|
|
213
|
+
* run. Two sets multiply; an advertisement does not.
|
|
214
|
+
*
|
|
215
|
+
* Written with {@link serviceKey}, so a store in another repository agrees
|
|
216
|
+
* on the encoding by calling the same function rather than by both
|
|
217
|
+
* spelling it out.
|
|
218
|
+
*/
|
|
219
|
+
readonly serves: ReadonlySet<string>;
|
|
181
220
|
readonly max: number;
|
|
182
221
|
readonly leaseMs: number;
|
|
183
222
|
}
|
package/dist/store-contract.d.ts
CHANGED
package/dist/store-contract.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
routeKey
|
|
3
|
-
|
|
2
|
+
routeKey,
|
|
3
|
+
serviceKey
|
|
4
|
+
} from "./chunk-XLWNHHLS.js";
|
|
4
5
|
|
|
5
6
|
// src/store-contract.ts
|
|
6
7
|
import { generateKeys, publicIdentityOf } from "@byollm/protocol";
|
|
@@ -41,6 +42,9 @@ var claimArgs = (over = {}) => {
|
|
|
41
42
|
owner: "alice",
|
|
42
43
|
device: publicIdentityOf(generateKeys(Date.now())),
|
|
43
44
|
kinds: /* @__PURE__ */ new Set(["llm.generate"]),
|
|
45
|
+
// Empty by default — `serves` matters only to a job that named a service.
|
|
46
|
+
// A contract case that exercises selection passes its own.
|
|
47
|
+
serves: /* @__PURE__ */ new Set(),
|
|
44
48
|
routes: new Set(
|
|
45
49
|
sites.flatMap((site) => owners.map((owner) => routeKey(site, owner)))
|
|
46
50
|
),
|
|
@@ -405,6 +409,95 @@ function describeStoreContract(name, options) {
|
|
|
405
409
|
expect(other).toEqual({ refused: "not-found" });
|
|
406
410
|
await done();
|
|
407
411
|
});
|
|
412
|
+
it("offers a selected job only to a device advertising that service", async () => {
|
|
413
|
+
const { store, done } = await make();
|
|
414
|
+
await store.enqueue({
|
|
415
|
+
id: "picked",
|
|
416
|
+
siteId: SITE,
|
|
417
|
+
stub: { ...stub("picked"), service: "studio" }
|
|
418
|
+
});
|
|
419
|
+
const wrong = await store.claim(
|
|
420
|
+
claimArgs({
|
|
421
|
+
runnerId: "runner_wrong",
|
|
422
|
+
serves: /* @__PURE__ */ new Set([serviceKey("llm.generate", "laptop")])
|
|
423
|
+
})
|
|
424
|
+
);
|
|
425
|
+
expect(wrong.map((job) => job.id)).toEqual([]);
|
|
426
|
+
const right = await store.claim(
|
|
427
|
+
claimArgs({
|
|
428
|
+
runnerId: "runner_right",
|
|
429
|
+
serves: /* @__PURE__ */ new Set([serviceKey("llm.generate", "studio")])
|
|
430
|
+
})
|
|
431
|
+
);
|
|
432
|
+
expect(right.map((job) => job.id)).toEqual(["picked"]);
|
|
433
|
+
await done();
|
|
434
|
+
});
|
|
435
|
+
it("never falls back from a selection to the default", async () => {
|
|
436
|
+
const { store, done } = await make();
|
|
437
|
+
await store.enqueue({
|
|
438
|
+
id: "no-fallback",
|
|
439
|
+
siteId: SITE,
|
|
440
|
+
stub: { ...stub("no-fallback"), service: "studio" }
|
|
441
|
+
});
|
|
442
|
+
const granted = await store.claim(
|
|
443
|
+
claimArgs({
|
|
444
|
+
// Serves the kind by default, advertises no service by that name.
|
|
445
|
+
kinds: /* @__PURE__ */ new Set(["llm.generate"]),
|
|
446
|
+
serves: /* @__PURE__ */ new Set()
|
|
447
|
+
})
|
|
448
|
+
);
|
|
449
|
+
expect(granted.map((job) => job.id)).toEqual([]);
|
|
450
|
+
expect((await store.job(SITE, "no-fallback"))?.state).toBe("queued");
|
|
451
|
+
await done();
|
|
452
|
+
});
|
|
453
|
+
it("sends an unselected job to the default, not to the menu", async () => {
|
|
454
|
+
const { store, done } = await make();
|
|
455
|
+
await store.enqueue({
|
|
456
|
+
id: "unselected",
|
|
457
|
+
siteId: SITE,
|
|
458
|
+
stub: stub("unselected")
|
|
459
|
+
});
|
|
460
|
+
const nothingDefault = await store.claim(
|
|
461
|
+
claimArgs({
|
|
462
|
+
runnerId: "runner_menu",
|
|
463
|
+
// A menu, and no default for this kind — the withheld state.
|
|
464
|
+
kinds: /* @__PURE__ */ new Set(),
|
|
465
|
+
serves: /* @__PURE__ */ new Set([
|
|
466
|
+
serviceKey("llm.generate", "studio"),
|
|
467
|
+
serviceKey("llm.generate", "laptop")
|
|
468
|
+
])
|
|
469
|
+
})
|
|
470
|
+
);
|
|
471
|
+
expect(nothingDefault.map((job) => job.id)).toEqual([]);
|
|
472
|
+
const hasDefault = await store.claim(
|
|
473
|
+
claimArgs({
|
|
474
|
+
runnerId: "runner_default",
|
|
475
|
+
kinds: /* @__PURE__ */ new Set(["llm.generate"]),
|
|
476
|
+
serves: /* @__PURE__ */ new Set([serviceKey("llm.generate", "studio")])
|
|
477
|
+
})
|
|
478
|
+
);
|
|
479
|
+
expect(hasDefault.map((job) => job.id)).toEqual(["unselected"]);
|
|
480
|
+
await done();
|
|
481
|
+
});
|
|
482
|
+
it("keeps the pair together, so two sets cannot multiply", async () => {
|
|
483
|
+
const { store, done } = await make();
|
|
484
|
+
await store.enqueue({
|
|
485
|
+
id: "crossed",
|
|
486
|
+
siteId: SITE,
|
|
487
|
+
stub: { ...stub("crossed"), kind: "llm.chat", service: "studio" }
|
|
488
|
+
});
|
|
489
|
+
const granted = await store.claim(
|
|
490
|
+
claimArgs({
|
|
491
|
+
kinds: /* @__PURE__ */ new Set(["llm.generate", "llm.chat"]),
|
|
492
|
+
serves: /* @__PURE__ */ new Set([
|
|
493
|
+
serviceKey("llm.generate", "studio"),
|
|
494
|
+
serviceKey("llm.chat", "claude")
|
|
495
|
+
])
|
|
496
|
+
})
|
|
497
|
+
);
|
|
498
|
+
expect(granted.map((job) => job.id)).toEqual([]);
|
|
499
|
+
await done();
|
|
500
|
+
});
|
|
408
501
|
it("remembers a device, and what it says it can run", async () => {
|
|
409
502
|
const { store, done } = await make();
|
|
410
503
|
const device = publicIdentityOf(generateKeys(3e12));
|
|
@@ -412,7 +505,8 @@ function describeStoreContract(name, options) {
|
|
|
412
505
|
runnerId: "runner_1",
|
|
413
506
|
owner: "alice",
|
|
414
507
|
device,
|
|
415
|
-
capabilities: [capability("llama3")]
|
|
508
|
+
capabilities: [capability("llama3")],
|
|
509
|
+
withheld: []
|
|
416
510
|
});
|
|
417
511
|
const known = await store.presence("runner_1");
|
|
418
512
|
expect(known?.owner).toBe("alice");
|
|
@@ -424,8 +518,16 @@ function describeStoreContract(name, options) {
|
|
|
424
518
|
const { store, done } = await make();
|
|
425
519
|
const device = publicIdentityOf(generateKeys(3000000000001));
|
|
426
520
|
const seen = { runnerId: "runner_2", owner: "alice", device };
|
|
427
|
-
await store.seen({
|
|
428
|
-
|
|
521
|
+
await store.seen({
|
|
522
|
+
...seen,
|
|
523
|
+
capabilities: [capability("llama3")],
|
|
524
|
+
withheld: []
|
|
525
|
+
});
|
|
526
|
+
await store.seen({
|
|
527
|
+
...seen,
|
|
528
|
+
capabilities: [capability("mistral")],
|
|
529
|
+
withheld: []
|
|
530
|
+
});
|
|
429
531
|
const known = await store.presence("runner_2");
|
|
430
532
|
expect(known?.capabilities.map((row) => row.model)).toEqual(["mistral"]);
|
|
431
533
|
await done();
|
|
@@ -434,19 +536,62 @@ function describeStoreContract(name, options) {
|
|
|
434
536
|
const { store, done } = await make();
|
|
435
537
|
const device = publicIdentityOf(generateKeys(3000000000002));
|
|
436
538
|
const seen = { runnerId: "runner_3", owner: "alice", device };
|
|
437
|
-
await store.seen({
|
|
438
|
-
|
|
539
|
+
await store.seen({
|
|
540
|
+
...seen,
|
|
541
|
+
capabilities: [capability("llama3")],
|
|
542
|
+
withheld: []
|
|
543
|
+
});
|
|
544
|
+
await store.seen({ ...seen, capabilities: [], withheld: [] });
|
|
439
545
|
expect((await store.presence("runner_3"))?.capabilities).toEqual([]);
|
|
440
546
|
await done();
|
|
441
547
|
});
|
|
548
|
+
it("remembers which kinds are withheld, and drops them when resolved", async () => {
|
|
549
|
+
const { store, done } = await make();
|
|
550
|
+
const device = publicIdentityOf(generateKeys(3000000000004));
|
|
551
|
+
const seen = { runnerId: "runner_withheld", owner: "alice", device };
|
|
552
|
+
await store.seen({
|
|
553
|
+
...seen,
|
|
554
|
+
capabilities: [],
|
|
555
|
+
withheld: [
|
|
556
|
+
{
|
|
557
|
+
kind: "llm.generate",
|
|
558
|
+
claimants: [
|
|
559
|
+
{ service: "ollama", offer: "team" },
|
|
560
|
+
{ service: "mlx", offer: "private" }
|
|
561
|
+
]
|
|
562
|
+
}
|
|
563
|
+
]
|
|
564
|
+
});
|
|
565
|
+
const held = await store.presence("runner_withheld");
|
|
566
|
+
expect(held?.withheld.map((row) => row.kind)).toEqual(["llm.generate"]);
|
|
567
|
+
expect(held?.withheld[0]?.claimants.map((c) => c.service)).toEqual([
|
|
568
|
+
"ollama",
|
|
569
|
+
"mlx"
|
|
570
|
+
]);
|
|
571
|
+
await store.seen({
|
|
572
|
+
...seen,
|
|
573
|
+
capabilities: [capability("llama3")],
|
|
574
|
+
withheld: []
|
|
575
|
+
});
|
|
576
|
+
expect((await store.presence("runner_withheld"))?.withheld).toEqual([]);
|
|
577
|
+
await done();
|
|
578
|
+
});
|
|
442
579
|
it("stamps presence from its own clock, and moves it on the next beat", async () => {
|
|
443
580
|
const { store, done } = await make();
|
|
444
581
|
const device = publicIdentityOf(generateKeys(3000000000003));
|
|
445
582
|
const seen = { runnerId: "runner_4", owner: "alice", device };
|
|
446
583
|
const before = await store.now();
|
|
447
|
-
const first = await store.seen({
|
|
584
|
+
const first = await store.seen({
|
|
585
|
+
...seen,
|
|
586
|
+
capabilities: [],
|
|
587
|
+
withheld: []
|
|
588
|
+
});
|
|
448
589
|
expect(first.lastSeenAt).toBeGreaterThanOrEqual(before);
|
|
449
|
-
const later = await store.seen({
|
|
590
|
+
const later = await store.seen({
|
|
591
|
+
...seen,
|
|
592
|
+
capabilities: [],
|
|
593
|
+
withheld: []
|
|
594
|
+
});
|
|
450
595
|
expect(later.lastSeenAt).toBeGreaterThanOrEqual(first.lastSeenAt);
|
|
451
596
|
await done();
|
|
452
597
|
});
|
|
@@ -456,13 +601,15 @@ function describeStoreContract(name, options) {
|
|
|
456
601
|
runnerId: "runner_5",
|
|
457
602
|
owner: "alice",
|
|
458
603
|
device: publicIdentityOf(generateKeys(3000000000004)),
|
|
459
|
-
capabilities: []
|
|
604
|
+
capabilities: [],
|
|
605
|
+
withheld: []
|
|
460
606
|
});
|
|
461
607
|
await store.seen({
|
|
462
608
|
runnerId: "runner_6",
|
|
463
609
|
owner: "bob",
|
|
464
610
|
device: publicIdentityOf(generateKeys(3000000000005)),
|
|
465
|
-
capabilities: []
|
|
611
|
+
capabilities: [],
|
|
612
|
+
withheld: []
|
|
466
613
|
});
|
|
467
614
|
const everyone = await store.everyone();
|
|
468
615
|
const ids = everyone.map((row) => row.runnerId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store-contract.ts"],"sourcesContent":["import { generateKeys, publicIdentityOf, type JobStub } from \"@byollm/protocol\";\nimport { describe, expect, it } from \"vitest\";\nimport { routeKey } from \"./state.js\";\nimport type { RoutingStore } from \"./store.js\";\n\n/**\n * The routing store's behaviour, written once and run against every\n * implementation — cloud_008 finding 54.\n *\n * There were two copies. This package tested `RelayState`; `byollm-cloud`\n * tested `ValkeyRoutingStore` with a file that opened by explaining it was\n * \"written once and parameterised… a second copy of the scenario is a second\n * place for two implementations to quietly diverge\" — and was itself the\n * second copy. It had drifted to sixteen cases against the eighteen in the\n * ledger, which is exactly the divergence the sentence predicted, happening\n * to the sentence.\n *\n * So the contract lives here, in the package that declares `RoutingStore`,\n * and both repositories import it. A store that cannot pass this is not a\n * routing store, whatever it implements.\n *\n * ## Why this ships in the published package\n *\n * Because the implementation that matters most is in another repository. A\n * contract only the author can run is a description; one a third party runs\n * against their own implementation is a contract. `@byollm/relay/store-contract`\n * is a subpath export so nothing that imports the relay itself pulls in a\n * test framework.\n *\n * ## What this cannot prove\n *\n * `CLAIM_ATOMIC` is a MUST and every case here would pass against a store\n * that read, decided and wrote in three steps — in one process there is\n * nothing to interleave. Concurrency belongs with the implementation that\n * has a network in it, and `byollm-cloud`'s suite runs it against Valkey with\n * many connections. Named here so the omission is a decision rather than an\n * oversight.\n */\n\n/** The control-plane site id these cases route under. */\nexport const CONTRACT_SITE = \"site_store\";\n\n/** A site's identity key id — byollm_009 Amendment A §A.3. */\nconst SITE_KEY_ID = \"BYOLLM-TEST-SITE-KEY-ID\";\n\nconst SITE = CONTRACT_SITE;\n\nconst stub = (id: string, owner = \"alice\"): JobStub => ({\n id,\n kind: \"llm.generate\",\n owner,\n site: SITE_KEY_ID,\n audience: \"private\",\n sizeClass: \"small\",\n streaming: false,\n deadlineAt: 4_102_444_800_000,\n});\n\n/** One advertised route, as a daemon describes it on every heartbeat. */\nconst capability = (model: string) => ({\n kind: \"llm.generate\" as const,\n service: model,\n isDefault: true,\n backendId: \"ollama\" as const,\n backendClass: \"process\" as const,\n model,\n offerScope: \"private\" as const,\n});\n\nconst ENVELOPE = {\n ciphertext: \"AAAA\",\n recipientKeyId: \"r\",\n senderKeyId: \"s\",\n direction: \"payload\" as const,\n deadlineAt: 4_102_444_800_000,\n};\n\n/**\n * A claim, with its routes written out — cloud_009 §3.\n *\n * `routes` replaced `siteId` + `owners`, and the cases that pass `owners`\n * below now pass the pairs those owners are reachable through. That rewrite\n * is the contract's own statement of the rule: there is no way to express\n * \"this owner, any site\" here, because that is not a thing consent says.\n */\nconst claimArgs = (\n over: { owners?: string[]; sites?: string[] } & Record<string, unknown> = {},\n) => {\n const { owners = [\"alice\"], sites = [SITE], ...rest } = over;\n return {\n runnerId: \"runner_1\",\n owner: \"alice\",\n device: publicIdentityOf(generateKeys(Date.now())),\n kinds: new Set([\"llm.generate\"]),\n routes: new Set(\n sites.flatMap((site) => owners.map((owner) => routeKey(site, owner))),\n ),\n max: 10,\n leaseMs: 60_000,\n ...rest,\n };\n};\n\nexport interface StoreContractOptions {\n /**\n * A fresh, empty store, and how to dispose of it.\n *\n * Arrow-typed rather than a method, because the caller passes these\n * around: a method signature lets `this` travel with the call, and a\n * factory read off an options object is exactly where that goes wrong.\n */\n readonly make: () => Promise<{\n store: RoutingStore;\n done: () => Promise<void>;\n }>;\n /**\n * Whether this store writes stubs as bytes and reads them back.\n *\n * An in-process store holds typed objects and cannot hold a stub it cannot\n * parse; a serialising one can, because what it wrote may have been written\n * by a previous version. The case that covers it is skipped rather than\n * hidden — a reader should know which half of this contract each store is\n * proving (cloud_008 §2.1a).\n */\n readonly serialising?: boolean;\n /** Write a stub's raw bytes, bypassing serialisation. */\n readonly writeRawStub?: (\n store: RoutingStore,\n id: string,\n raw: string,\n ) => Promise<void>;\n}\n\n/** Run the contract. Call inside a suite; it declares its own `describe`. */\nexport function describeStoreContract(\n name: string,\n options: StoreContractOptions,\n): void {\n const { make, serialising, writeRawStub } = options;\n describe(`the routing store — ${name}`, () => {\n it(\"is idempotent by job id\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n await store.claim(claimArgs());\n // A republish must not disturb work in flight — byollm_009 §4.2's replay\n // argument rests on it.\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n expect((await store.job(SITE, \"a\"))?.state).toBe(\"awaiting-payload\");\n await done();\n });\n\n it(\"gives two sites the same id without either seeing the other\", async () => {\n // cloud_009 §3. Keyed by the bare id, the second site's enqueue returned\n // the *first* site's job (cloud_008 finding 58), and the refusal that\n // fixed it was a cross-tenant existence oracle: a site knows its own stub\n // is well-formed, so any answer it can tell apart from success confirms\n // somebody else holds that id. Keyed by (site, id), the collision does\n // not exist and there is nothing to answer.\n const { store, done } = await make();\n await store.enqueue({ id: \"shared\", siteId: SITE, stub: stub(\"shared\") });\n await store.enqueue({\n id: \"shared\",\n siteId: \"site_other\",\n stub: stub(\"shared\", \"bob\"),\n });\n\n // Two jobs, each its own site's.\n expect((await store.job(SITE, \"shared\"))?.stub.owner).toBe(\"alice\");\n expect((await store.job(\"site_other\", \"shared\"))?.stub.owner).toBe(\"bob\");\n\n // And a claim for one site does not see the other's, which is the\n // property the key exists for rather than a restatement of it.\n const granted = await store.claim(claimArgs());\n expect(granted.map((job) => job.id)).toEqual([\"shared\"]);\n expect(granted[0]?.owner).toBe(\"alice\");\n\n // The same site republishing is still absorbed — byollm_009 §4.2's\n // replay argument, which is what idempotence is for.\n const replay = await store.enqueue({\n id: \"shared\",\n siteId: SITE,\n stub: stub(\"shared\"),\n });\n expect(replay).toEqual(await store.job(SITE, \"shared\"));\n await done();\n });\n\n it(\"grants only what the owners set allows\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"mine\", siteId: SITE, stub: stub(\"mine\") });\n await store.enqueue({\n id: \"theirs\",\n siteId: SITE,\n stub: stub(\"theirs\", \"mallory\"),\n });\n const granted = await store.claim(claimArgs());\n expect(granted.map((job) => job.id)).toEqual([\"mine\"]);\n await done();\n });\n\n it(\"refuses a stale lease and honours the current one\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n await store.seal({ jobId: \"a\", siteId: SITE, envelope: ENVELOPE });\n\n expect(\n await store.takePayload({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: \"an-older-grant\",\n }),\n ).toEqual({ refused: \"stale-lease\" });\n\n expect(\n await store.takePayload({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n }),\n ).toEqual({ envelope: ENVELOPE });\n await done();\n });\n\n it(\"will not answer for one job with another job's lease\", async () => {\n // cloud_009 §3. Holder-scoped calls carry a lease id and no site, so the\n // store resolves the job *from the lease* — and a lease id belonging to a\n // different job must not be a way to reach that job's payload.\n //\n // A mutation that dropped the \"does this lease's job match the id the\n // caller named\" check survived every other case in this contract, on both\n // implementations, because nothing else here ever presents a mismatched\n // pair. The holder of a valid grant is exactly the party who could try\n // it.\n const { store, done } = await make();\n await store.enqueue({ id: \"mine\", siteId: SITE, stub: stub(\"mine\") });\n await store.enqueue({ id: \"other\", siteId: SITE, stub: stub(\"other\") });\n const granted = await store.claim(claimArgs());\n const mine = granted.find((job) => job.id === \"mine\");\n const other = granted.find((job) => job.id === \"other\");\n await store.seal({ jobId: \"other\", siteId: SITE, envelope: ENVELOPE });\n\n // The right runner, a real lease, the wrong job.\n expect(\n await store.takePayload({\n jobId: \"other\",\n runnerId: \"runner_1\",\n leaseId: mine!.lease.id,\n }),\n ).toEqual({ refused: \"stale-lease\" });\n\n // And the honest pairing still works, so this is not \"refuse everything\".\n expect(\n await store.takePayload({\n jobId: \"other\",\n runnerId: \"runner_1\",\n leaseId: other!.lease.id,\n }),\n ).toEqual({ envelope: ENVELOPE });\n await done();\n });\n\n it(\"renews a grant it still holds, and extends the sweep with it\", async () => {\n // cloud_008 §0.6, at the contract level: renewal has to be one operation,\n // because between a read and a write another replica can sweep the lease\n // — and the renewal would then resurrect a grant on a job already back in\n // the queue. In Valkey that is a script; in memory it is a method; the\n // guarantee is the same one, so it is tested here rather than twice.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs({ leaseMs: 1_000 }));\n\n const renewed = await store.renewLeases({\n runnerId: \"runner_1\",\n leases: [{ jobId: \"a\", leaseId: granted!.lease.id }],\n leaseMs: 60_000,\n });\n\n expect(renewed.lost).toEqual([]);\n expect(renewed.renewed.map((r) => r.jobId)).toEqual([\"a\"]);\n // The store's own clock did the arithmetic — the caller passed a duration,\n // never an instant, which is what keeps two replicas from measuring one\n // lease against two clocks (cloud_006 §3.4).\n expect(renewed.renewed[0]!.expiresAt).toBeGreaterThan(\n granted!.lease.expiresAt,\n );\n\n // And it is the *stored* grant that moved, not just the number returned.\n // Reporting a renewal without performing one is the mutation that\n // survived the first version of the relay's own test for this.\n expect((await store.job(SITE, \"a\"))?.claimedBy?.leaseExpiresAt).toBe(\n renewed.renewed[0]!.expiresAt,\n );\n await done();\n });\n\n it(\"reports a lease the runner no longer holds as lost, and renews nothing\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs({ leaseMs: 1_000 }));\n const before = (await store.job(SITE, \"a\"))?.claimedBy?.leaseExpiresAt;\n\n const renewed = await store.renewLeases({\n runnerId: \"runner_1\",\n leases: [{ jobId: \"a\", leaseId: \"a-grant-that-ended\" }],\n leaseMs: 60_000,\n });\n\n expect(renewed.renewed).toEqual([]);\n expect(renewed.lost).toEqual([\n { jobId: \"a\", leaseId: \"a-grant-that-ended\" },\n ]);\n // A refusal must not advance anything — the current holder's grant is\n // untouched by somebody else's stale renewal.\n expect((await store.job(SITE, \"a\"))?.claimedBy?.leaseExpiresAt).toBe(\n before,\n );\n expect((await store.job(SITE, \"a\"))?.claimedBy?.leaseId).toBe(\n granted!.lease.id,\n );\n await done();\n });\n\n it(\"does not hand out a stub it cannot parse\", async () => {\n // cloud_008 §2.1a, and the case is not hypothetical: two jobs enqueued\n // before alpha.15 had no `site`, came back in a claim, and the daemon's\n // `.strict()` parse rejected the whole response. Two dead rows denied\n // claims to every device on the hub, and the queue could not drain past\n // them.\n //\n // The store had `JSON.parse(stub) as JobStub` — trusting what it wrote,\n // when what it wrote was written by a previous version. A routing store\n // outlives the deployment that filled it, so a wire change to `JobStub`\n // is a data migration whether or not anyone plans one.\n //\n // Only meaningful against a store that serialises: `RelayState` holds\n // typed objects and cannot reach this state, so it passes by\n // construction — which is worth saying rather than hiding, because a\n // reader should know which half of this contract each store is proving.\n const { store, done } = await make();\n if (!serialising || writeRawStub === undefined) {\n await done();\n return;\n }\n\n await store.enqueue({ id: \"good\", siteId: SITE, stub: stub(\"good\") });\n await store.enqueue({ id: \"old\", siteId: SITE, stub: stub(\"old\") });\n // Exactly what alpha.14 wrote: a stub with no `site`.\n const legacy = { ...stub(\"old\") } as Record<string, unknown>;\n delete legacy[\"site\"];\n await writeRawStub(store, \"old\", JSON.stringify(legacy));\n\n const granted = await store.claim(claimArgs({ max: 10 }));\n\n // The good one is still handed out — \"return nothing\" would pass a test\n // that only checked the bad one was absent, and would stop all routing.\n expect(granted.map((job) => job.id)).toEqual([\"good\"]);\n // And the bad one is back in the queue rather than stuck holding a lease\n // nobody received.\n expect((await store.job(SITE, \"old\"))?.state).toBe(\"queued\");\n await done();\n });\n\n it(\"honours a self job's audience\", async () => {\n // cloud_008 §2.1 at the contract level. The owners set is everyone this\n // device may run for, which for a Team owner's machine is the whole\n // roster — right for public and named, wrong for the one audience a user\n // picks because they want their own machine.\n const { store, done } = await make();\n await store.enqueue({\n id: \"private\",\n siteId: SITE,\n stub: { ...stub(\"private\", \"alice\"), audience: \"private\" },\n });\n\n // A roster owner's machine: may run alice's work in general.\n const granted = await store.claim(\n claimArgs({ owner: \"owner\", owners: [\"owner\", \"alice\"] }),\n );\n\n expect(granted).toEqual([]);\n expect((await store.job(SITE, \"private\"))?.state).toBe(\"queued\");\n await done();\n });\n\n it(\"still offers that job to its owner's own machine\", async () => {\n const { store, done } = await make();\n await store.enqueue({\n id: \"private\",\n siteId: SITE,\n stub: { ...stub(\"private\", \"alice\"), audience: \"private\" },\n });\n const granted = await store.claim(\n claimArgs({ owner: \"alice\", owners: [\"alice\"] }),\n );\n expect(granted.map((job) => job.id)).toEqual([\"private\"]);\n await done();\n });\n\n it(\"does not offer a job back to the runner that refused it\", async () => {\n // `REFUSAL_NOT_REOFFERED`. `releaseLeases` gained an **optional** reason,\n // which means a store can ignore it and still typecheck — this class has\n // now diverged from the interface that way twice, so the contract is the\n // only thing that catches it.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n\n await store.releaseLeases({\n runnerId: \"runner_1\",\n leases: [{ jobId: \"a\", leaseId: granted!.lease.id }],\n reason: \"refused\",\n });\n\n expect(await store.claim(claimArgs())).toEqual([]);\n expect((await store.job(SITE, \"a\"))?.state).toBe(\"queued\");\n // And somebody else may still run it.\n expect(\n (await store.claim(claimArgs({ runnerId: \"runner_2\" }))).map(\n (j) => j.id,\n ),\n ).toEqual([\"a\"]);\n await done();\n });\n\n it(\"keeps a job claimable by a runner that only went away\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n\n await store.releaseLeases({\n runnerId: \"runner_1\",\n leases: [{ jobId: \"a\", leaseId: granted!.lease.id }],\n reason: \"shutdown\",\n });\n\n expect((await store.claim(claimArgs())).map((j) => j.id)).toEqual([\"a\"]);\n await done();\n });\n\n it(\"stops offering a job past its deadline, and drops the ciphertext\", async () => {\n // cloud_008 §2.2. `deadlineAt` travelled on every stub and nothing read\n // it, so expired jobs were offered forever and their sealed payloads kept\n // for as long as the store lived.\n const { store, done } = await make();\n await store.enqueue({\n id: \"late\",\n siteId: SITE,\n stub: { ...stub(\"late\"), deadlineAt: Date.now() - 1_000 },\n });\n\n expect(await store.claim(claimArgs())).toEqual([]);\n expect(await store.job(SITE, \"late\")).toBeUndefined();\n await done();\n });\n\n it(\"names a cancelled job to the device holding it, and offers it to nobody\", async () => {\n // cloud_008 §2.2.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n await store.claim(claimArgs());\n\n expect(await store.cancel({ jobId: \"a\", siteId: SITE })).toBe(true);\n // Named by grant — V1-3, so a daemon holding two sites' `a` knows\n // which one the site withdrew.\n const held = (await store.job(SITE, \"a\"))?.claimedBy?.leaseId;\n expect(await store.cancelRequests(\"runner_1\")).toEqual([\n { jobId: \"a\", leaseId: held },\n ]);\n\n // Scoped to the caller's site: a site must not reach another's work by\n // guessing an id.\n expect(await store.cancel({ jobId: \"a\", siteId: \"someone_else\" })).toBe(\n false,\n );\n await done();\n });\n\n it(\"records a result once\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n\n const first = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n envelope: ENVELOPE,\n disposition: \"ok\",\n });\n const replay = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n envelope: { ...ENVELOPE, ciphertext: \"different\" },\n disposition: \"error\",\n });\n\n expect(first).toEqual({ accepted: true, state: \"done\" });\n // `duplicate` — cloud_008 §3.6. Case 18 above is the one that says why.\n expect(replay).toEqual({\n accepted: false,\n duplicate: true,\n state: \"done\",\n });\n // The property, not the boolean: the second result did not overwrite.\n expect((await store.job(SITE, \"a\"))?.disposition).toBe(\"ok\");\n await done();\n });\n\n it(\"answers the device that finished it with `duplicate`\", async () => {\n // Contract case 18 — cloud_008 §3.6, and the eighteenth exists because\n // the compiler cannot see any of this: the return type's `duplicate` is\n // optional, so a store that never sets it typechecks perfectly while\n // enforcing `RESULT_IDEMPOTENT` by accident or not at all.\n //\n // A daemon whose acknowledgment was lost hears that its answer is already\n // recorded, rather than that its lease is stale — the second message\n // invents a worry about a result safely on disk.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n\n const first = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n envelope: ENVELOPE,\n disposition: \"ok\",\n });\n expect(first).toEqual({ accepted: true, state: \"done\" });\n\n const replay = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n envelope: { ...ENVELOPE, ciphertext: \"a-different-result\" },\n disposition: \"error\",\n });\n expect(replay).toEqual({\n accepted: false,\n duplicate: true,\n state: \"done\",\n });\n\n // A *different* device, on a job that is terminal, gets the refusal it\n // would get for one that is not — otherwise the two answers differ and a\n // job id becomes a terminality probe.\n const stranger = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_2\",\n leaseId: granted!.lease.id,\n envelope: ENVELOPE,\n disposition: \"ok\",\n });\n expect(stranger).toEqual({ refused: \"not-holder\" });\n\n // And the first answer is what survived, which is the property rather\n // than any of the booleans above.\n expect((await store.job(SITE, \"a\"))?.disposition).toBe(\"ok\");\n await done();\n });\n\n it(\"refuses a result produced under a grant that ended\", async () => {\n // cloud_008 §1.4a at the contract level, and it belongs here more than\n // anywhere: `RoutingStore.complete` gained `leaseId` and this class kept\n // typechecking without it, because a parameter object with fewer\n // properties is assignable to one with more. The relay would have\n // enforced LEASE_HONORED on the memory store and not on the store that\n // runs in production, with nothing red on the way.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n await store.claim(claimArgs());\n\n const late = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: \"a-grant-that-ended\",\n envelope: ENVELOPE,\n disposition: \"ok\",\n });\n\n expect(late).toEqual({ refused: \"stale-lease\" });\n // Untouched: the current holder can still finish it.\n expect((await store.job(SITE, \"a\"))?.state).toBe(\"awaiting-payload\");\n expect((await store.job(SITE, \"a\"))?.result).toBeUndefined();\n await done();\n });\n\n it(\"refuses a payload for a job that already finished [V1-6]\", async () => {\n // The holder and lease checks both pass for a job this runner finished\n // moments ago — completing does not end the grant. So a replayed fetch\n // set `state = 'running'` on a **done** job: the site stopped being able\n // to collect its result, and the sweep requeued completed work as though\n // the device had died holding it.\n //\n // Which is `RESULT_IDEMPOTENT` broken through the other door: a\n // duplicate request undoing a finished job.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n await store.seal({ jobId: \"a\", siteId: SITE, envelope: ENVELOPE });\n await store.takePayload({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n });\n await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n envelope: ENVELOPE,\n disposition: \"ok\",\n });\n\n const replay = await store.takePayload({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n });\n // Its own refusal, not `not-ready`: one says keep asking and this says\n // stop, and a daemon that read them alike would poll a finished job\n // until its lease ran out.\n expect(replay).toEqual({ refused: \"terminal\" });\n // And the finished job is still finished, which is the property.\n expect((await store.job(SITE, \"a\"))?.state).toBe(\"done\");\n await done();\n });\n\n it(\"tells a runner nothing about another site's job id [V1-8]\", async () => {\n // Job ids are chosen per site, so a bare id is a guess about somebody\n // else's namespace. The answer used to depend on whether that guess\n // landed: an id belonging to another tenant came back `not-holder`,\n // an id belonging to nobody came back `not-found`. Two status codes,\n // one bit of somebody else's business — finding 58's oracle, reached\n // through the holder door instead of the site plane.\n const { store, done } = await make();\n // Another tenant's job, under an id this caller can guess but a site it\n // does not route for.\n await store.enqueue({\n id: \"secret\",\n siteId: \"site_somebody_else\",\n stub: stub(\"secret\"),\n });\n await store.enqueue({ id: \"mine\", siteId: SITE, stub: stub(\"mine\") });\n const granted = await store.claim(claimArgs());\n const mine = granted.find((job) => job.id === \"mine\");\n\n // Asking about a job this runner does not hold, under a lease it does.\n const other = await store.takePayload({\n jobId: \"secret\",\n runnerId: \"runner_1\",\n leaseId: mine!.lease.id,\n });\n const absent = await store.takePayload({\n jobId: \"no-such-job-anywhere\",\n runnerId: \"runner_1\",\n leaseId: mine!.lease.id,\n });\n\n expect(other).toEqual(absent);\n expect(other).toEqual({ refused: \"not-found\" });\n await done();\n });\n\n // ── presence ────────────────────────────────────────────────────────\n //\n // The seam had no contract coverage at all: presence was exercised\n // against `RelayState` and nothing held a shared store to the same\n // behaviour. That is the shape the pairing ceiling was found in — one\n // seam, two implementations, and the check driving the one nobody\n // deploys — so these land with `Presence.capabilities` rather than after\n // somebody notices.\n\n it(\"remembers a device, and what it says it can run\", async () => {\n const { store, done } = await make();\n const device = publicIdentityOf(generateKeys(3_000_000_000_000));\n await store.seen({\n runnerId: \"runner_1\",\n owner: \"alice\",\n device,\n capabilities: [capability(\"llama3\")],\n });\n\n const known = await store.presence(\"runner_1\");\n expect(known?.owner).toBe(\"alice\");\n expect(known?.device.identity).toBe(device.identity);\n expect(known?.capabilities.map((row) => row.model)).toEqual([\"llama3\"]);\n await done();\n });\n\n it(\"replaces the matrix rather than merging it\", async () => {\n // The heartbeat re-sends the whole matrix every time so a server never\n // matches against a stale one. A store that kept the union would go on\n // advertising a backend the machine has lost — and work would route to\n // it, which is worse than forgetting one it still has.\n const { store, done } = await make();\n const device = publicIdentityOf(generateKeys(3_000_000_000_001));\n const seen = { runnerId: \"runner_2\", owner: \"alice\", device };\n await store.seen({ ...seen, capabilities: [capability(\"llama3\")] });\n await store.seen({ ...seen, capabilities: [capability(\"mistral\")] });\n\n const known = await store.presence(\"runner_2\");\n expect(known?.capabilities.map((row) => row.model)).toEqual([\"mistral\"]);\n await done();\n });\n\n it(\"keeps an empty matrix, because empty is an answer\", async () => {\n // A paired machine with no healthy backend — the connect-first ruling's\n // whole point. A store that treated empty as \"nothing to record\" would\n // leave the last non-empty matrix standing and the machines page would\n // show models that are gone.\n const { store, done } = await make();\n const device = publicIdentityOf(generateKeys(3_000_000_000_002));\n const seen = { runnerId: \"runner_3\", owner: \"alice\", device };\n await store.seen({ ...seen, capabilities: [capability(\"llama3\")] });\n await store.seen({ ...seen, capabilities: [] });\n\n expect((await store.presence(\"runner_3\"))?.capabilities).toEqual([]);\n await done();\n });\n\n it(\"stamps presence from its own clock, and moves it on the next beat\", async () => {\n // `lastSeenAt` is liveness, and liveness is only true if something\n // advances it. It was written once at pairing and never again, so it\n // reported the pairing time under the name \"last seen\" — a field that\n // is quietly a different fact.\n const { store, done } = await make();\n const device = publicIdentityOf(generateKeys(3_000_000_000_003));\n const seen = { runnerId: \"runner_4\", owner: \"alice\", device };\n\n const before = await store.now();\n const first = await store.seen({ ...seen, capabilities: [] });\n expect(first.lastSeenAt).toBeGreaterThanOrEqual(before);\n\n const later = await store.seen({ ...seen, capabilities: [] });\n expect(later.lastSeenAt).toBeGreaterThanOrEqual(first.lastSeenAt);\n await done();\n });\n\n it(\"lists everyone it has seen\", async () => {\n const { store, done } = await make();\n await store.seen({\n runnerId: \"runner_5\",\n owner: \"alice\",\n device: publicIdentityOf(generateKeys(3_000_000_000_004)),\n capabilities: [],\n });\n await store.seen({\n runnerId: \"runner_6\",\n owner: \"bob\",\n device: publicIdentityOf(generateKeys(3_000_000_000_005)),\n capabilities: [],\n });\n\n const everyone = await store.everyone();\n const ids = everyone.map((row) => row.runnerId);\n expect(ids).toContain(\"runner_5\");\n expect(ids).toContain(\"runner_6\");\n await done();\n });\n\n it(\"does not know a runner it has never seen\", async () => {\n const { store, done } = await make();\n expect(await store.presence(\"runner_never\")).toBeUndefined();\n await done();\n });\n\n it(\"stamps deadlines from its own clock\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const before = await store.now();\n const [granted] = await store.claim(claimArgs({ leaseMs: 45_000 }));\n const after = await store.now();\n\n // Bracketed rather than exact: a real store's clock moves between the two\n // reads, which is the whole reason it is the store's clock and not ours.\n expect(granted!.lease.expiresAt).toBeGreaterThanOrEqual(before + 45_000);\n expect(granted!.lease.expiresAt).toBeLessThanOrEqual(after + 45_000);\n await done();\n });\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/store-contract.ts"],"sourcesContent":["import { generateKeys, publicIdentityOf, type JobStub } from \"@byollm/protocol\";\nimport { describe, expect, it } from \"vitest\";\nimport { routeKey, serviceKey } from \"./state.js\";\nimport type { RoutingStore } from \"./store.js\";\n\n/**\n * The routing store's behaviour, written once and run against every\n * implementation — cloud_008 finding 54.\n *\n * There were two copies. This package tested `RelayState`; `byollm-cloud`\n * tested `ValkeyRoutingStore` with a file that opened by explaining it was\n * \"written once and parameterised… a second copy of the scenario is a second\n * place for two implementations to quietly diverge\" — and was itself the\n * second copy. It had drifted to sixteen cases against the eighteen in the\n * ledger, which is exactly the divergence the sentence predicted, happening\n * to the sentence.\n *\n * So the contract lives here, in the package that declares `RoutingStore`,\n * and both repositories import it. A store that cannot pass this is not a\n * routing store, whatever it implements.\n *\n * ## Why this ships in the published package\n *\n * Because the implementation that matters most is in another repository. A\n * contract only the author can run is a description; one a third party runs\n * against their own implementation is a contract. `@byollm/relay/store-contract`\n * is a subpath export so nothing that imports the relay itself pulls in a\n * test framework.\n *\n * ## What this cannot prove\n *\n * `CLAIM_ATOMIC` is a MUST and every case here would pass against a store\n * that read, decided and wrote in three steps — in one process there is\n * nothing to interleave. Concurrency belongs with the implementation that\n * has a network in it, and `byollm-cloud`'s suite runs it against Valkey with\n * many connections. Named here so the omission is a decision rather than an\n * oversight.\n */\n\n/** The control-plane site id these cases route under. */\nexport const CONTRACT_SITE = \"site_store\";\n\n/** A site's identity key id — byollm_009 Amendment A §A.3. */\nconst SITE_KEY_ID = \"BYOLLM-TEST-SITE-KEY-ID\";\n\nconst SITE = CONTRACT_SITE;\n\nconst stub = (id: string, owner = \"alice\"): JobStub => ({\n id,\n kind: \"llm.generate\",\n owner,\n site: SITE_KEY_ID,\n audience: \"private\",\n sizeClass: \"small\",\n streaming: false,\n deadlineAt: 4_102_444_800_000,\n});\n\n/** One advertised route, as a daemon describes it on every heartbeat. */\nconst capability = (model: string) => ({\n kind: \"llm.generate\" as const,\n service: model,\n isDefault: true,\n backendId: \"ollama\" as const,\n backendClass: \"process\" as const,\n model,\n offerScope: \"private\" as const,\n});\n\nconst ENVELOPE = {\n ciphertext: \"AAAA\",\n recipientKeyId: \"r\",\n senderKeyId: \"s\",\n direction: \"payload\" as const,\n deadlineAt: 4_102_444_800_000,\n};\n\n/**\n * A claim, with its routes written out — cloud_009 §3.\n *\n * `routes` replaced `siteId` + `owners`, and the cases that pass `owners`\n * below now pass the pairs those owners are reachable through. That rewrite\n * is the contract's own statement of the rule: there is no way to express\n * \"this owner, any site\" here, because that is not a thing consent says.\n */\nconst claimArgs = (\n over: { owners?: string[]; sites?: string[] } & Record<string, unknown> = {},\n) => {\n const { owners = [\"alice\"], sites = [SITE], ...rest } = over;\n return {\n runnerId: \"runner_1\",\n owner: \"alice\",\n device: publicIdentityOf(generateKeys(Date.now())),\n kinds: new Set([\"llm.generate\"]),\n // Empty by default — `serves` matters only to a job that named a service.\n // A contract case that exercises selection passes its own.\n serves: new Set<string>(),\n routes: new Set(\n sites.flatMap((site) => owners.map((owner) => routeKey(site, owner))),\n ),\n max: 10,\n leaseMs: 60_000,\n ...rest,\n };\n};\n\nexport interface StoreContractOptions {\n /**\n * A fresh, empty store, and how to dispose of it.\n *\n * Arrow-typed rather than a method, because the caller passes these\n * around: a method signature lets `this` travel with the call, and a\n * factory read off an options object is exactly where that goes wrong.\n */\n readonly make: () => Promise<{\n store: RoutingStore;\n done: () => Promise<void>;\n }>;\n /**\n * Whether this store writes stubs as bytes and reads them back.\n *\n * An in-process store holds typed objects and cannot hold a stub it cannot\n * parse; a serialising one can, because what it wrote may have been written\n * by a previous version. The case that covers it is skipped rather than\n * hidden — a reader should know which half of this contract each store is\n * proving (cloud_008 §2.1a).\n */\n readonly serialising?: boolean;\n /** Write a stub's raw bytes, bypassing serialisation. */\n readonly writeRawStub?: (\n store: RoutingStore,\n id: string,\n raw: string,\n ) => Promise<void>;\n}\n\n/** Run the contract. Call inside a suite; it declares its own `describe`. */\nexport function describeStoreContract(\n name: string,\n options: StoreContractOptions,\n): void {\n const { make, serialising, writeRawStub } = options;\n describe(`the routing store — ${name}`, () => {\n it(\"is idempotent by job id\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n await store.claim(claimArgs());\n // A republish must not disturb work in flight — byollm_009 §4.2's replay\n // argument rests on it.\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n expect((await store.job(SITE, \"a\"))?.state).toBe(\"awaiting-payload\");\n await done();\n });\n\n it(\"gives two sites the same id without either seeing the other\", async () => {\n // cloud_009 §3. Keyed by the bare id, the second site's enqueue returned\n // the *first* site's job (cloud_008 finding 58), and the refusal that\n // fixed it was a cross-tenant existence oracle: a site knows its own stub\n // is well-formed, so any answer it can tell apart from success confirms\n // somebody else holds that id. Keyed by (site, id), the collision does\n // not exist and there is nothing to answer.\n const { store, done } = await make();\n await store.enqueue({ id: \"shared\", siteId: SITE, stub: stub(\"shared\") });\n await store.enqueue({\n id: \"shared\",\n siteId: \"site_other\",\n stub: stub(\"shared\", \"bob\"),\n });\n\n // Two jobs, each its own site's.\n expect((await store.job(SITE, \"shared\"))?.stub.owner).toBe(\"alice\");\n expect((await store.job(\"site_other\", \"shared\"))?.stub.owner).toBe(\"bob\");\n\n // And a claim for one site does not see the other's, which is the\n // property the key exists for rather than a restatement of it.\n const granted = await store.claim(claimArgs());\n expect(granted.map((job) => job.id)).toEqual([\"shared\"]);\n expect(granted[0]?.owner).toBe(\"alice\");\n\n // The same site republishing is still absorbed — byollm_009 §4.2's\n // replay argument, which is what idempotence is for.\n const replay = await store.enqueue({\n id: \"shared\",\n siteId: SITE,\n stub: stub(\"shared\"),\n });\n expect(replay).toEqual(await store.job(SITE, \"shared\"));\n await done();\n });\n\n it(\"grants only what the owners set allows\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"mine\", siteId: SITE, stub: stub(\"mine\") });\n await store.enqueue({\n id: \"theirs\",\n siteId: SITE,\n stub: stub(\"theirs\", \"mallory\"),\n });\n const granted = await store.claim(claimArgs());\n expect(granted.map((job) => job.id)).toEqual([\"mine\"]);\n await done();\n });\n\n it(\"refuses a stale lease and honours the current one\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n await store.seal({ jobId: \"a\", siteId: SITE, envelope: ENVELOPE });\n\n expect(\n await store.takePayload({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: \"an-older-grant\",\n }),\n ).toEqual({ refused: \"stale-lease\" });\n\n expect(\n await store.takePayload({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n }),\n ).toEqual({ envelope: ENVELOPE });\n await done();\n });\n\n it(\"will not answer for one job with another job's lease\", async () => {\n // cloud_009 §3. Holder-scoped calls carry a lease id and no site, so the\n // store resolves the job *from the lease* — and a lease id belonging to a\n // different job must not be a way to reach that job's payload.\n //\n // A mutation that dropped the \"does this lease's job match the id the\n // caller named\" check survived every other case in this contract, on both\n // implementations, because nothing else here ever presents a mismatched\n // pair. The holder of a valid grant is exactly the party who could try\n // it.\n const { store, done } = await make();\n await store.enqueue({ id: \"mine\", siteId: SITE, stub: stub(\"mine\") });\n await store.enqueue({ id: \"other\", siteId: SITE, stub: stub(\"other\") });\n const granted = await store.claim(claimArgs());\n const mine = granted.find((job) => job.id === \"mine\");\n const other = granted.find((job) => job.id === \"other\");\n await store.seal({ jobId: \"other\", siteId: SITE, envelope: ENVELOPE });\n\n // The right runner, a real lease, the wrong job.\n expect(\n await store.takePayload({\n jobId: \"other\",\n runnerId: \"runner_1\",\n leaseId: mine!.lease.id,\n }),\n ).toEqual({ refused: \"stale-lease\" });\n\n // And the honest pairing still works, so this is not \"refuse everything\".\n expect(\n await store.takePayload({\n jobId: \"other\",\n runnerId: \"runner_1\",\n leaseId: other!.lease.id,\n }),\n ).toEqual({ envelope: ENVELOPE });\n await done();\n });\n\n it(\"renews a grant it still holds, and extends the sweep with it\", async () => {\n // cloud_008 §0.6, at the contract level: renewal has to be one operation,\n // because between a read and a write another replica can sweep the lease\n // — and the renewal would then resurrect a grant on a job already back in\n // the queue. In Valkey that is a script; in memory it is a method; the\n // guarantee is the same one, so it is tested here rather than twice.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs({ leaseMs: 1_000 }));\n\n const renewed = await store.renewLeases({\n runnerId: \"runner_1\",\n leases: [{ jobId: \"a\", leaseId: granted!.lease.id }],\n leaseMs: 60_000,\n });\n\n expect(renewed.lost).toEqual([]);\n expect(renewed.renewed.map((r) => r.jobId)).toEqual([\"a\"]);\n // The store's own clock did the arithmetic — the caller passed a duration,\n // never an instant, which is what keeps two replicas from measuring one\n // lease against two clocks (cloud_006 §3.4).\n expect(renewed.renewed[0]!.expiresAt).toBeGreaterThan(\n granted!.lease.expiresAt,\n );\n\n // And it is the *stored* grant that moved, not just the number returned.\n // Reporting a renewal without performing one is the mutation that\n // survived the first version of the relay's own test for this.\n expect((await store.job(SITE, \"a\"))?.claimedBy?.leaseExpiresAt).toBe(\n renewed.renewed[0]!.expiresAt,\n );\n await done();\n });\n\n it(\"reports a lease the runner no longer holds as lost, and renews nothing\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs({ leaseMs: 1_000 }));\n const before = (await store.job(SITE, \"a\"))?.claimedBy?.leaseExpiresAt;\n\n const renewed = await store.renewLeases({\n runnerId: \"runner_1\",\n leases: [{ jobId: \"a\", leaseId: \"a-grant-that-ended\" }],\n leaseMs: 60_000,\n });\n\n expect(renewed.renewed).toEqual([]);\n expect(renewed.lost).toEqual([\n { jobId: \"a\", leaseId: \"a-grant-that-ended\" },\n ]);\n // A refusal must not advance anything — the current holder's grant is\n // untouched by somebody else's stale renewal.\n expect((await store.job(SITE, \"a\"))?.claimedBy?.leaseExpiresAt).toBe(\n before,\n );\n expect((await store.job(SITE, \"a\"))?.claimedBy?.leaseId).toBe(\n granted!.lease.id,\n );\n await done();\n });\n\n it(\"does not hand out a stub it cannot parse\", async () => {\n // cloud_008 §2.1a, and the case is not hypothetical: two jobs enqueued\n // before alpha.15 had no `site`, came back in a claim, and the daemon's\n // `.strict()` parse rejected the whole response. Two dead rows denied\n // claims to every device on the hub, and the queue could not drain past\n // them.\n //\n // The store had `JSON.parse(stub) as JobStub` — trusting what it wrote,\n // when what it wrote was written by a previous version. A routing store\n // outlives the deployment that filled it, so a wire change to `JobStub`\n // is a data migration whether or not anyone plans one.\n //\n // Only meaningful against a store that serialises: `RelayState` holds\n // typed objects and cannot reach this state, so it passes by\n // construction — which is worth saying rather than hiding, because a\n // reader should know which half of this contract each store is proving.\n const { store, done } = await make();\n if (!serialising || writeRawStub === undefined) {\n await done();\n return;\n }\n\n await store.enqueue({ id: \"good\", siteId: SITE, stub: stub(\"good\") });\n await store.enqueue({ id: \"old\", siteId: SITE, stub: stub(\"old\") });\n // Exactly what alpha.14 wrote: a stub with no `site`.\n const legacy = { ...stub(\"old\") } as Record<string, unknown>;\n delete legacy[\"site\"];\n await writeRawStub(store, \"old\", JSON.stringify(legacy));\n\n const granted = await store.claim(claimArgs({ max: 10 }));\n\n // The good one is still handed out — \"return nothing\" would pass a test\n // that only checked the bad one was absent, and would stop all routing.\n expect(granted.map((job) => job.id)).toEqual([\"good\"]);\n // And the bad one is back in the queue rather than stuck holding a lease\n // nobody received.\n expect((await store.job(SITE, \"old\"))?.state).toBe(\"queued\");\n await done();\n });\n\n it(\"honours a self job's audience\", async () => {\n // cloud_008 §2.1 at the contract level. The owners set is everyone this\n // device may run for, which for a Team owner's machine is the whole\n // roster — right for public and named, wrong for the one audience a user\n // picks because they want their own machine.\n const { store, done } = await make();\n await store.enqueue({\n id: \"private\",\n siteId: SITE,\n stub: { ...stub(\"private\", \"alice\"), audience: \"private\" },\n });\n\n // A roster owner's machine: may run alice's work in general.\n const granted = await store.claim(\n claimArgs({ owner: \"owner\", owners: [\"owner\", \"alice\"] }),\n );\n\n expect(granted).toEqual([]);\n expect((await store.job(SITE, \"private\"))?.state).toBe(\"queued\");\n await done();\n });\n\n it(\"still offers that job to its owner's own machine\", async () => {\n const { store, done } = await make();\n await store.enqueue({\n id: \"private\",\n siteId: SITE,\n stub: { ...stub(\"private\", \"alice\"), audience: \"private\" },\n });\n const granted = await store.claim(\n claimArgs({ owner: \"alice\", owners: [\"alice\"] }),\n );\n expect(granted.map((job) => job.id)).toEqual([\"private\"]);\n await done();\n });\n\n it(\"does not offer a job back to the runner that refused it\", async () => {\n // `REFUSAL_NOT_REOFFERED`. `releaseLeases` gained an **optional** reason,\n // which means a store can ignore it and still typecheck — this class has\n // now diverged from the interface that way twice, so the contract is the\n // only thing that catches it.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n\n await store.releaseLeases({\n runnerId: \"runner_1\",\n leases: [{ jobId: \"a\", leaseId: granted!.lease.id }],\n reason: \"refused\",\n });\n\n expect(await store.claim(claimArgs())).toEqual([]);\n expect((await store.job(SITE, \"a\"))?.state).toBe(\"queued\");\n // And somebody else may still run it.\n expect(\n (await store.claim(claimArgs({ runnerId: \"runner_2\" }))).map(\n (j) => j.id,\n ),\n ).toEqual([\"a\"]);\n await done();\n });\n\n it(\"keeps a job claimable by a runner that only went away\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n\n await store.releaseLeases({\n runnerId: \"runner_1\",\n leases: [{ jobId: \"a\", leaseId: granted!.lease.id }],\n reason: \"shutdown\",\n });\n\n expect((await store.claim(claimArgs())).map((j) => j.id)).toEqual([\"a\"]);\n await done();\n });\n\n it(\"stops offering a job past its deadline, and drops the ciphertext\", async () => {\n // cloud_008 §2.2. `deadlineAt` travelled on every stub and nothing read\n // it, so expired jobs were offered forever and their sealed payloads kept\n // for as long as the store lived.\n const { store, done } = await make();\n await store.enqueue({\n id: \"late\",\n siteId: SITE,\n stub: { ...stub(\"late\"), deadlineAt: Date.now() - 1_000 },\n });\n\n expect(await store.claim(claimArgs())).toEqual([]);\n expect(await store.job(SITE, \"late\")).toBeUndefined();\n await done();\n });\n\n it(\"names a cancelled job to the device holding it, and offers it to nobody\", async () => {\n // cloud_008 §2.2.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n await store.claim(claimArgs());\n\n expect(await store.cancel({ jobId: \"a\", siteId: SITE })).toBe(true);\n // Named by grant — V1-3, so a daemon holding two sites' `a` knows\n // which one the site withdrew.\n const held = (await store.job(SITE, \"a\"))?.claimedBy?.leaseId;\n expect(await store.cancelRequests(\"runner_1\")).toEqual([\n { jobId: \"a\", leaseId: held },\n ]);\n\n // Scoped to the caller's site: a site must not reach another's work by\n // guessing an id.\n expect(await store.cancel({ jobId: \"a\", siteId: \"someone_else\" })).toBe(\n false,\n );\n await done();\n });\n\n it(\"records a result once\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n\n const first = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n envelope: ENVELOPE,\n disposition: \"ok\",\n });\n const replay = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n envelope: { ...ENVELOPE, ciphertext: \"different\" },\n disposition: \"error\",\n });\n\n expect(first).toEqual({ accepted: true, state: \"done\" });\n // `duplicate` — cloud_008 §3.6. Case 18 above is the one that says why.\n expect(replay).toEqual({\n accepted: false,\n duplicate: true,\n state: \"done\",\n });\n // The property, not the boolean: the second result did not overwrite.\n expect((await store.job(SITE, \"a\"))?.disposition).toBe(\"ok\");\n await done();\n });\n\n it(\"answers the device that finished it with `duplicate`\", async () => {\n // Contract case 18 — cloud_008 §3.6, and the eighteenth exists because\n // the compiler cannot see any of this: the return type's `duplicate` is\n // optional, so a store that never sets it typechecks perfectly while\n // enforcing `RESULT_IDEMPOTENT` by accident or not at all.\n //\n // A daemon whose acknowledgment was lost hears that its answer is already\n // recorded, rather than that its lease is stale — the second message\n // invents a worry about a result safely on disk.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n\n const first = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n envelope: ENVELOPE,\n disposition: \"ok\",\n });\n expect(first).toEqual({ accepted: true, state: \"done\" });\n\n const replay = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n envelope: { ...ENVELOPE, ciphertext: \"a-different-result\" },\n disposition: \"error\",\n });\n expect(replay).toEqual({\n accepted: false,\n duplicate: true,\n state: \"done\",\n });\n\n // A *different* device, on a job that is terminal, gets the refusal it\n // would get for one that is not — otherwise the two answers differ and a\n // job id becomes a terminality probe.\n const stranger = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_2\",\n leaseId: granted!.lease.id,\n envelope: ENVELOPE,\n disposition: \"ok\",\n });\n expect(stranger).toEqual({ refused: \"not-holder\" });\n\n // And the first answer is what survived, which is the property rather\n // than any of the booleans above.\n expect((await store.job(SITE, \"a\"))?.disposition).toBe(\"ok\");\n await done();\n });\n\n it(\"refuses a result produced under a grant that ended\", async () => {\n // cloud_008 §1.4a at the contract level, and it belongs here more than\n // anywhere: `RoutingStore.complete` gained `leaseId` and this class kept\n // typechecking without it, because a parameter object with fewer\n // properties is assignable to one with more. The relay would have\n // enforced LEASE_HONORED on the memory store and not on the store that\n // runs in production, with nothing red on the way.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n await store.claim(claimArgs());\n\n const late = await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: \"a-grant-that-ended\",\n envelope: ENVELOPE,\n disposition: \"ok\",\n });\n\n expect(late).toEqual({ refused: \"stale-lease\" });\n // Untouched: the current holder can still finish it.\n expect((await store.job(SITE, \"a\"))?.state).toBe(\"awaiting-payload\");\n expect((await store.job(SITE, \"a\"))?.result).toBeUndefined();\n await done();\n });\n\n it(\"refuses a payload for a job that already finished [V1-6]\", async () => {\n // The holder and lease checks both pass for a job this runner finished\n // moments ago — completing does not end the grant. So a replayed fetch\n // set `state = 'running'` on a **done** job: the site stopped being able\n // to collect its result, and the sweep requeued completed work as though\n // the device had died holding it.\n //\n // Which is `RESULT_IDEMPOTENT` broken through the other door: a\n // duplicate request undoing a finished job.\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const [granted] = await store.claim(claimArgs());\n await store.seal({ jobId: \"a\", siteId: SITE, envelope: ENVELOPE });\n await store.takePayload({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n });\n await store.complete({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n envelope: ENVELOPE,\n disposition: \"ok\",\n });\n\n const replay = await store.takePayload({\n jobId: \"a\",\n runnerId: \"runner_1\",\n leaseId: granted!.lease.id,\n });\n // Its own refusal, not `not-ready`: one says keep asking and this says\n // stop, and a daemon that read them alike would poll a finished job\n // until its lease ran out.\n expect(replay).toEqual({ refused: \"terminal\" });\n // And the finished job is still finished, which is the property.\n expect((await store.job(SITE, \"a\"))?.state).toBe(\"done\");\n await done();\n });\n\n it(\"tells a runner nothing about another site's job id [V1-8]\", async () => {\n // Job ids are chosen per site, so a bare id is a guess about somebody\n // else's namespace. The answer used to depend on whether that guess\n // landed: an id belonging to another tenant came back `not-holder`,\n // an id belonging to nobody came back `not-found`. Two status codes,\n // one bit of somebody else's business — finding 58's oracle, reached\n // through the holder door instead of the site plane.\n const { store, done } = await make();\n // Another tenant's job, under an id this caller can guess but a site it\n // does not route for.\n await store.enqueue({\n id: \"secret\",\n siteId: \"site_somebody_else\",\n stub: stub(\"secret\"),\n });\n await store.enqueue({ id: \"mine\", siteId: SITE, stub: stub(\"mine\") });\n const granted = await store.claim(claimArgs());\n const mine = granted.find((job) => job.id === \"mine\");\n\n // Asking about a job this runner does not hold, under a lease it does.\n const other = await store.takePayload({\n jobId: \"secret\",\n runnerId: \"runner_1\",\n leaseId: mine!.lease.id,\n });\n const absent = await store.takePayload({\n jobId: \"no-such-job-anywhere\",\n runnerId: \"runner_1\",\n leaseId: mine!.lease.id,\n });\n\n expect(other).toEqual(absent);\n expect(other).toEqual({ refused: \"not-found\" });\n await done();\n });\n\n // ── selection ───────────────────────────────────────────────────────\n //\n // byollm_016 Phase B. Every store must reason about (kind, service?)\n // identically, and it lives here rather than in one store's own tests\n // because that is the shape the pairing ceiling was found in: one seam,\n // two implementations, and the check driving the one nobody deploys.\n\n it(\"offers a selected job only to a device advertising that service\", async () => {\n const { store, done } = await make();\n await store.enqueue({\n id: \"picked\",\n siteId: SITE,\n stub: { ...stub(\"picked\"), service: \"studio\" },\n });\n\n // A device that serves the kind, by a different name. It has a default\n // for `llm.generate` — so it would take an *unselected* job — and it\n // must not take this one.\n const wrong = await store.claim(\n claimArgs({\n runnerId: \"runner_wrong\",\n serves: new Set([serviceKey(\"llm.generate\", \"laptop\")]),\n }),\n );\n expect(wrong.map((job) => job.id)).toEqual([]);\n\n const right = await store.claim(\n claimArgs({\n runnerId: \"runner_right\",\n serves: new Set([serviceKey(\"llm.generate\", \"studio\")]),\n }),\n );\n expect(right.map((job) => job.id)).toEqual([\"picked\"]);\n await done();\n });\n\n it(\"never falls back from a selection to the default\", async () => {\n // The substitution NO_PAYLOAD_ROUTING forbids, as a store behaviour. A\n // job that named `studio` and meets a device serving only its own\n // default must stay queued and wait for a device that has `studio` —\n // quietly running it somewhere else is precisely how \"pick from my\n // list\" decays into \"ask for anything and get something\".\n const { store, done } = await make();\n await store.enqueue({\n id: \"no-fallback\",\n siteId: SITE,\n stub: { ...stub(\"no-fallback\"), service: \"studio\" },\n });\n\n const granted = await store.claim(\n claimArgs({\n // Serves the kind by default, advertises no service by that name.\n kinds: new Set([\"llm.generate\"]),\n serves: new Set<string>(),\n }),\n );\n expect(granted.map((job) => job.id)).toEqual([]);\n expect((await store.job(SITE, \"no-fallback\"))?.state).toBe(\"queued\");\n await done();\n });\n\n it(\"sends an unselected job to the default, not to the menu\", async () => {\n // The other half, and the one a store gets wrong by being generous. A\n // device advertising two services for one kind has both in `serves` and\n // only the chosen one in `kinds`. An unselected job must follow `kinds`:\n // matching on the menu would put it on whichever row sorted first,\n // which is the guess the withheld mechanism exists to refuse.\n const { store, done } = await make();\n await store.enqueue({\n id: \"unselected\",\n siteId: SITE,\n stub: stub(\"unselected\"),\n });\n\n const nothingDefault = await store.claim(\n claimArgs({\n runnerId: \"runner_menu\",\n // A menu, and no default for this kind — the withheld state.\n kinds: new Set<string>(),\n serves: new Set([\n serviceKey(\"llm.generate\", \"studio\"),\n serviceKey(\"llm.generate\", \"laptop\"),\n ]),\n }),\n );\n expect(nothingDefault.map((job) => job.id)).toEqual([]);\n\n const hasDefault = await store.claim(\n claimArgs({\n runnerId: \"runner_default\",\n kinds: new Set([\"llm.generate\"]),\n serves: new Set([serviceKey(\"llm.generate\", \"studio\")]),\n }),\n );\n expect(hasDefault.map((job) => job.id)).toEqual([\"unselected\"]);\n await done();\n });\n\n it(\"keeps the pair together, so two sets cannot multiply\", async () => {\n // The `routes` argument, one axis over. A device serving `studio` for\n // `llm.generate` and `claude` for `llm.chat` has both kinds and both\n // names; a store holding them as two sets would answer yes to\n // (`llm.chat`, `studio`) — a combination nobody advertised and nothing\n // can run.\n const { store, done } = await make();\n await store.enqueue({\n id: \"crossed\",\n siteId: SITE,\n stub: { ...stub(\"crossed\"), kind: \"llm.chat\", service: \"studio\" },\n });\n\n const granted = await store.claim(\n claimArgs({\n kinds: new Set([\"llm.generate\", \"llm.chat\"]),\n serves: new Set([\n serviceKey(\"llm.generate\", \"studio\"),\n serviceKey(\"llm.chat\", \"claude\"),\n ]),\n }),\n );\n expect(granted.map((job) => job.id)).toEqual([]);\n await done();\n });\n\n // ── presence ────────────────────────────────────────────────────────\n //\n // The seam had no contract coverage at all: presence was exercised\n // against `RelayState` and nothing held a shared store to the same\n // behaviour. That is the shape the pairing ceiling was found in — one\n // seam, two implementations, and the check driving the one nobody\n // deploys — so these land with `Presence.capabilities` rather than after\n // somebody notices.\n\n it(\"remembers a device, and what it says it can run\", async () => {\n const { store, done } = await make();\n const device = publicIdentityOf(generateKeys(3_000_000_000_000));\n await store.seen({\n runnerId: \"runner_1\",\n owner: \"alice\",\n device,\n capabilities: [capability(\"llama3\")],\n withheld: [],\n });\n\n const known = await store.presence(\"runner_1\");\n expect(known?.owner).toBe(\"alice\");\n expect(known?.device.identity).toBe(device.identity);\n expect(known?.capabilities.map((row) => row.model)).toEqual([\"llama3\"]);\n await done();\n });\n\n it(\"replaces the matrix rather than merging it\", async () => {\n // The heartbeat re-sends the whole matrix every time so a server never\n // matches against a stale one. A store that kept the union would go on\n // advertising a backend the machine has lost — and work would route to\n // it, which is worse than forgetting one it still has.\n const { store, done } = await make();\n const device = publicIdentityOf(generateKeys(3_000_000_000_001));\n const seen = { runnerId: \"runner_2\", owner: \"alice\", device };\n await store.seen({\n ...seen,\n capabilities: [capability(\"llama3\")],\n withheld: [],\n });\n await store.seen({\n ...seen,\n capabilities: [capability(\"mistral\")],\n withheld: [],\n });\n\n const known = await store.presence(\"runner_2\");\n expect(known?.capabilities.map((row) => row.model)).toEqual([\"mistral\"]);\n await done();\n });\n\n it(\"keeps an empty matrix, because empty is an answer\", async () => {\n // A paired machine with no healthy backend — the connect-first ruling's\n // whole point. A store that treated empty as \"nothing to record\" would\n // leave the last non-empty matrix standing and the machines page would\n // show models that are gone.\n const { store, done } = await make();\n const device = publicIdentityOf(generateKeys(3_000_000_000_002));\n const seen = { runnerId: \"runner_3\", owner: \"alice\", device };\n await store.seen({\n ...seen,\n capabilities: [capability(\"llama3\")],\n withheld: [],\n });\n await store.seen({ ...seen, capabilities: [], withheld: [] });\n\n expect((await store.presence(\"runner_3\"))?.capabilities).toEqual([]);\n await done();\n });\n\n it(\"remembers which kinds are withheld, and drops them when resolved\", async () => {\n // byollm_016. Two services answering one kind with no `defaults` entry\n // is a state only the daemon can see: from the matrix alone a withheld\n // kind and an absent one are the same shape, so a store that dropped\n // this field would leave the owner's page saying \"nothing serves\n // llm.generate\" — true, and useless, when the real sentence is \"two\n // services answer it and you have not chosen\".\n //\n // It lives in the contract rather than one store's tests because the\n // pairing ceiling was found exactly that way: one seam, two\n // implementations, and the check driving the one nobody deploys.\n const { store, done } = await make();\n const device = publicIdentityOf(generateKeys(3_000_000_000_004));\n const seen = { runnerId: \"runner_withheld\", owner: \"alice\", device };\n\n await store.seen({\n ...seen,\n capabilities: [],\n withheld: [\n {\n kind: \"llm.generate\",\n claimants: [\n { service: \"ollama\", offer: \"team\" },\n { service: \"mlx\", offer: \"private\" },\n ],\n },\n ],\n });\n\n const held = await store.presence(\"runner_withheld\");\n expect(held?.withheld.map((row) => row.kind)).toEqual([\"llm.generate\"]);\n // The claimants survive the round trip, because naming them is the\n // whole difference between a prompt and a complaint.\n expect(held?.withheld[0]?.claimants.map((c) => c.service)).toEqual([\n \"ollama\",\n \"mlx\",\n ]);\n\n // The owner chooses a default: the kind resolves and stops being\n // reported, or the page goes on asking for a decision already made.\n await store.seen({\n ...seen,\n capabilities: [capability(\"llama3\")],\n withheld: [],\n });\n expect((await store.presence(\"runner_withheld\"))?.withheld).toEqual([]);\n await done();\n });\n\n it(\"stamps presence from its own clock, and moves it on the next beat\", async () => {\n // `lastSeenAt` is liveness, and liveness is only true if something\n // advances it. It was written once at pairing and never again, so it\n // reported the pairing time under the name \"last seen\" — a field that\n // is quietly a different fact.\n const { store, done } = await make();\n const device = publicIdentityOf(generateKeys(3_000_000_000_003));\n const seen = { runnerId: \"runner_4\", owner: \"alice\", device };\n\n const before = await store.now();\n const first = await store.seen({\n ...seen,\n capabilities: [],\n withheld: [],\n });\n expect(first.lastSeenAt).toBeGreaterThanOrEqual(before);\n\n const later = await store.seen({\n ...seen,\n capabilities: [],\n withheld: [],\n });\n expect(later.lastSeenAt).toBeGreaterThanOrEqual(first.lastSeenAt);\n await done();\n });\n\n it(\"lists everyone it has seen\", async () => {\n const { store, done } = await make();\n await store.seen({\n runnerId: \"runner_5\",\n owner: \"alice\",\n device: publicIdentityOf(generateKeys(3_000_000_000_004)),\n capabilities: [],\n withheld: [],\n });\n await store.seen({\n runnerId: \"runner_6\",\n owner: \"bob\",\n device: publicIdentityOf(generateKeys(3_000_000_000_005)),\n capabilities: [],\n withheld: [],\n });\n\n const everyone = await store.everyone();\n const ids = everyone.map((row) => row.runnerId);\n expect(ids).toContain(\"runner_5\");\n expect(ids).toContain(\"runner_6\");\n await done();\n });\n\n it(\"does not know a runner it has never seen\", async () => {\n const { store, done } = await make();\n expect(await store.presence(\"runner_never\")).toBeUndefined();\n await done();\n });\n\n it(\"stamps deadlines from its own clock\", async () => {\n const { store, done } = await make();\n await store.enqueue({ id: \"a\", siteId: SITE, stub: stub(\"a\") });\n const before = await store.now();\n const [granted] = await store.claim(claimArgs({ leaseMs: 45_000 }));\n const after = await store.now();\n\n // Bracketed rather than exact: a real store's clock moves between the two\n // reads, which is the whole reason it is the store's clock and not ours.\n expect(granted!.lease.expiresAt).toBeGreaterThanOrEqual(before + 45_000);\n expect(granted!.lease.expiresAt).toBeLessThanOrEqual(after + 45_000);\n await done();\n });\n });\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byollm/relay",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.46",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The reference relay: routes sealed byollm jobs between sites and daemons, holding no decryption keys by construction.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"zod": "^4.1.13",
|
|
34
|
-
"@byollm/protocol": "0.1.0-alpha.
|
|
34
|
+
"@byollm/protocol": "0.1.0-alpha.46"
|
|
35
35
|
},
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@supabase/supabase-js": "^2.112.2",
|
|
41
41
|
"vitest": "^4.1.10",
|
|
42
|
-
"@byollm/
|
|
43
|
-
"@byollm/
|
|
44
|
-
"byollm": "0.1.0-alpha.
|
|
42
|
+
"@byollm/conformance": "0.1.0-alpha.46",
|
|
43
|
+
"@byollm/server": "0.1.0-alpha.46",
|
|
44
|
+
"byollm": "0.1.0-alpha.46"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"vitest": ">=3"
|