@byollm/relay 0.1.0-alpha.21 → 0.1.0-alpha.23
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 +15 -3
- package/dist/index.d.ts +45 -512
- package/dist/index.js +83 -3
- package/dist/index.js.map +1 -1
- package/dist/store-C_NtPAvT.d.ts +512 -0
- package/dist/store-contract.d.ts +67 -0
- package/dist/store-contract.js +305 -0
- package/dist/store-contract.js.map +1 -0
- package/package.json +18 -5
package/dist/index.js
CHANGED
|
@@ -180,7 +180,15 @@ var DaemonPlane = class {
|
|
|
180
180
|
kinds: new Set(request.capabilities.map((c) => c.kind)),
|
|
181
181
|
// The projection, collapsed to data the store can match on — a
|
|
182
182
|
// predicate does not travel.
|
|
183
|
-
|
|
183
|
+
//
|
|
184
|
+
// `routableOwners`, not `ownersRunnableBy`: the roster says whose
|
|
185
|
+
// work *may* land here and consent says whether it moves at all. A
|
|
186
|
+
// paused consent (cloud_008 finding 48) leaves this set empty rather
|
|
187
|
+
// than refusing the call, which is the whole difference between "we
|
|
188
|
+
// are waiting for you to read something" and "a human cut you off".
|
|
189
|
+
owners: new Set(
|
|
190
|
+
this.#deps.projection.routableOwners(device.owner, this.#deps.siteId)
|
|
191
|
+
),
|
|
184
192
|
max: request.max,
|
|
185
193
|
leaseMs: this.#deps.leaseMs
|
|
186
194
|
});
|
|
@@ -382,7 +390,31 @@ var ConsentRecord = z2.object({
|
|
|
382
390
|
/** The user, as the control plane identifies them. */
|
|
383
391
|
owner: z2.string().min(1),
|
|
384
392
|
/** Which site this consent is for. Scoped: consent is never global. */
|
|
385
|
-
siteId: z2.string().min(1)
|
|
393
|
+
siteId: z2.string().min(1),
|
|
394
|
+
/**
|
|
395
|
+
* The consent stands, and nothing routes under it — cloud_008 finding 48.
|
|
396
|
+
*
|
|
397
|
+
* The disclosure this user agreed to no longer describes their
|
|
398
|
+
* arrangements: they read that their prompts stay on machines they own,
|
|
399
|
+
* and they have since been added to a roster whose owner can read them.
|
|
400
|
+
* Until they have been shown the other sentence and clicked, their work
|
|
401
|
+
* does not move.
|
|
402
|
+
*
|
|
403
|
+
* **A third state, because the two we had are both wrong here.** Dropping
|
|
404
|
+
* the consent makes `consentFor` return null, and the daemon plane reads
|
|
405
|
+
* exactly that as revoked: heartbeat answers `revoked: true` with `lost:
|
|
406
|
+
* all`, and the daemon prints "this runner was revoked" and *deletes its
|
|
407
|
+
* pairing*. So a user whose team changed a setting would be told a human
|
|
408
|
+
* cut them off, lose their pinned keys, and have to re-run `byollm
|
|
409
|
+
* connect` after re-consenting. Under cloud_009 that is worse still: the
|
|
410
|
+
* pairing is keyed by origin, so one stale consent would drop the pairing
|
|
411
|
+
* for every other site reached through that hub.
|
|
412
|
+
*
|
|
413
|
+
* Reporting it as revoked is the same falsehood finding 48 exists to
|
|
414
|
+
* delete, told one layer down. So the record stays, the relationship
|
|
415
|
+
* stays, and the routing stops.
|
|
416
|
+
*/
|
|
417
|
+
paused: z2.boolean().default(false)
|
|
386
418
|
}).strict();
|
|
387
419
|
var RosterRecord = z2.object({
|
|
388
420
|
/** Stable id for the group, used only inside the relay. */
|
|
@@ -460,7 +492,15 @@ var Projection = class {
|
|
|
460
492
|
deviceByFingerprint(identityPublic) {
|
|
461
493
|
return this.#fixture.devices.find((d) => d.device.identity === identityPublic) ?? null;
|
|
462
494
|
}
|
|
463
|
-
/**
|
|
495
|
+
/**
|
|
496
|
+
* The consent binding this owner to this site, if it exists and stands.
|
|
497
|
+
*
|
|
498
|
+
* **Liveness, not routing.** A paused consent is returned here: the
|
|
499
|
+
* relationship exists, the daemon is not revoked, the pairing stands. Ask
|
|
500
|
+
* {@link Projection.mayRouteFor} before moving anybody's work — the two
|
|
501
|
+
* questions have different answers and one method answering both is how a
|
|
502
|
+
* paused user would quietly start routing again.
|
|
503
|
+
*/
|
|
464
504
|
consentFor(owner, siteId) {
|
|
465
505
|
const revoked = this.#fixture.revoked.some(
|
|
466
506
|
(r) => r.owner === owner && r.siteId === siteId
|
|
@@ -470,6 +510,46 @@ var Projection = class {
|
|
|
470
510
|
(c) => c.owner === owner && c.siteId === siteId
|
|
471
511
|
) ?? null;
|
|
472
512
|
}
|
|
513
|
+
/**
|
|
514
|
+
* May this owner's work move for this site, right now?
|
|
515
|
+
*
|
|
516
|
+
* Consent exists, was not revoked, and is not paused. The routing question,
|
|
517
|
+
* kept apart from {@link Projection.consentFor}'s liveness one so that a
|
|
518
|
+
* caller has to pick which it means.
|
|
519
|
+
*/
|
|
520
|
+
mayRouteFor(owner, siteId) {
|
|
521
|
+
const consent = this.consentFor(owner, siteId);
|
|
522
|
+
return consent !== null && !consent.paused;
|
|
523
|
+
}
|
|
524
|
+
/** Whether this pair is consented and paused — what heartbeat reports. */
|
|
525
|
+
pausedFor(owner, siteId) {
|
|
526
|
+
return this.consentFor(owner, siteId)?.paused === true;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Whose work this device may run for this site — the set a claim carries.
|
|
530
|
+
*
|
|
531
|
+
* {@link Projection.ownersRunnableBy} collapsed and then filtered by
|
|
532
|
+
* consent, which is two things this relay was doing in one place and one
|
|
533
|
+
* place respectively:
|
|
534
|
+
*
|
|
535
|
+
* - **The device's own owner is checked first**, and an unroutable one
|
|
536
|
+
* empties the whole set. A machine whose owner has not agreed to this
|
|
537
|
+
* site's current terms runs nothing for it, including a roster member's
|
|
538
|
+
* work: the roster says whose jobs may land here, and consent says
|
|
539
|
+
* whether this machine is available to the site at all.
|
|
540
|
+
* - **Every job owner is checked too.** That check did not exist. Consent
|
|
541
|
+
* was enforced by the daemon plane's blanket revoked guard, which asks
|
|
542
|
+
* only about the *claiming* device's owner — so a roster member who never
|
|
543
|
+
* consented to a site could have their work claimed by their admin's
|
|
544
|
+
* machine, which is `CONSENT_BEFORE_ROUTE` read the other way round. The
|
|
545
|
+
* site plane does not check consent at enqueue either, so nothing did.
|
|
546
|
+
*/
|
|
547
|
+
routableOwners(deviceOwner, siteId) {
|
|
548
|
+
if (!this.mayRouteFor(deviceOwner, siteId)) return [];
|
|
549
|
+
return this.ownersRunnableBy(deviceOwner).filter(
|
|
550
|
+
(owner) => this.mayRouteFor(owner, siteId)
|
|
551
|
+
);
|
|
552
|
+
}
|
|
473
553
|
/**
|
|
474
554
|
* Every owner whose work this device's owner may run, as a list.
|
|
475
555
|
*
|