@scp-dev/hub 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _scp_dev_core from '@scp-dev/core';
2
- import { Envelope, RelayCore, CoreOptions, EndpointRow, PolicySubject, ScopeSubject, ScopeNode, ScopeDirection, Admission, MessageRow, EndpointView, ScopeCap, ScopeEntry, Claim, SendParams, SendResult, EndpointKind, Presence, StatusState, Verdict, JudgeModelConfig, JudgeClient, Sql, JudgePolicy, CrossAccountLink, XDelivered, XListed, ActivityRow, XRelease } from '@scp-dev/core';
2
+ import { Envelope, RelayCore, CoreOptions, EndpointRow, PolicySubject, ScopeSubject, ScopeNode, ScopeDirection, Admission, MessageRow, EndpointView, ScopeCap, ScopeEntry, Claim, SendParams, SendResult, EndpointKind, Presence, StatusState, Verdict, JudgeModelConfig, JudgeClient, Sql, JudgePolicy, Wake, CrossAccountLink, XDelivered, XListed, ActivityRow, XRelease } from '@scp-dev/core';
3
3
 
4
4
  type RelayAuth = Envelope["from"]["auth"];
5
5
  /** a machine name: one relay host of an account */
@@ -59,6 +59,8 @@ interface MirrorView extends MirrorScope {
59
59
  presence?: Presence;
60
60
  last_seen?: string | null;
61
61
  title?: string | null;
62
+ /** an agent's {@link Wake}; a value this hub does not know is kept as none */
63
+ wake?: string | null;
62
64
  /** the handle the endpoint had before a rename: its mirror is renamed in place */
63
65
  was?: string;
64
66
  }
@@ -567,7 +569,7 @@ interface GraphNode {
567
569
  status: EndpointView["status"];
568
570
  last_seen: string | null;
569
571
  parent: string | null;
570
- wake?: string | null;
572
+ wake?: Wake | null;
571
573
  }
572
574
  /** `spawn`: parent to child; `message`: sender to recipient, with the count and newest send in the graph's window */
573
575
  type GraphEdge = {
package/dist/index.js CHANGED
@@ -22,7 +22,8 @@ import {
22
22
  unreachable,
23
23
  validHandle,
24
24
  validHarness,
25
- validSelector
25
+ validSelector,
26
+ WAKES
26
27
  } from "@scp-dev/core";
27
28
  var MACHINE_NAME = /^[a-z0-9][a-z0-9-]{0,31}$/;
28
29
  var REMOTE = /^[a-z0-9][a-z0-9._-]{0,63}\/([a-z0-9][a-z0-9._-]{0,62})?$/;
@@ -1283,7 +1284,7 @@ var FederatedCore = class extends RelayCore {
1283
1284
  const was = this.view(before);
1284
1285
  const presence = was.presence !== view.presence;
1285
1286
  const status = before.status_state !== after.status_state || before.status_note !== after.status_note;
1286
- const other = ["kind", "harness", "model", "cwd", "labels", "title", "tree", "parent_ep", "depth", "rules", "caps", "incarnation"].some(
1287
+ const other = ["kind", "harness", "model", "cwd", "labels", "title", "wake", "tree", "parent_ep", "depth", "rules", "caps", "incarnation"].some(
1287
1288
  (field) => before[field] !== after[field]
1288
1289
  );
1289
1290
  return presence || status || other ? { view, added: false, presence, status } : null;
@@ -1351,6 +1352,7 @@ var FederatedCore = class extends RelayCore {
1351
1352
  rules: rules === void 0 ? row.rules : rules && (rules.in || rules.out) ? JSON.stringify(rules) : null,
1352
1353
  caps,
1353
1354
  title: scope.title !== void 0 ? scope.title : fresh ? null : row.title,
1355
+ wake: scope.wake !== void 0 ? scope.wake : fresh ? null : row.wake,
1354
1356
  incarnation: scope.incarnation ?? row.incarnation
1355
1357
  };
1356
1358
  }
@@ -1504,6 +1506,7 @@ function parseScope(view) {
1504
1506
  throw new RelayError("too_large", `an endpoint's rules and caps are more than ${SCOPE_BYTES} bytes`);
1505
1507
  if (given("title"))
1506
1508
  out.title = view.title === null ? null : cleanText(typeof view.title === "string" ? view.title.replace(/\s+/g, " ") : view.title, "title", 64) || null;
1509
+ if (given("wake")) out.wake = typeof view.wake === "string" && view.wake !== "none" && WAKES.includes(view.wake) ? view.wake : null;
1507
1510
  if (given("incarnation")) {
1508
1511
  if (view.incarnation !== null && (typeof view.incarnation !== "string" || !INCARNATION.test(view.incarnation))) throw bad("incarnation");
1509
1512
  out.incarnation = view.incarnation ?? null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scp-dev/hub",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Swarm Communication Protocol federation and account hub: mirrored endpoints across machines, bridges, direct clients and cross-account delivery.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://scp.dev",
@@ -29,7 +29,7 @@
29
29
  "typecheck": "tsc -p ."
30
30
  },
31
31
  "dependencies": {
32
- "@scp-dev/core": "0.1.3"
32
+ "@scp-dev/core": "0.1.4"
33
33
  },
34
34
  "devDependencies": {
35
35
  "tsup": "^8.5.1"
package/src/federation.ts CHANGED
@@ -43,6 +43,8 @@ import {
43
43
  validHandle,
44
44
  validHarness,
45
45
  validSelector,
46
+ type Wake,
47
+ WAKES,
46
48
  } from "@scp-dev/core"
47
49
 
48
50
  export type RelayAuth = Envelope["from"]["auth"]
@@ -121,6 +123,8 @@ export interface MirrorView extends MirrorScope {
121
123
  presence?: Presence
122
124
  last_seen?: string | null
123
125
  title?: string | null
126
+ /** an agent's {@link Wake}; a value this hub does not know is kept as none */
127
+ wake?: string | null
124
128
  /** the handle the endpoint had before a rename: its mirror is renamed in place */
125
129
  was?: string
126
130
  }
@@ -142,6 +146,7 @@ interface ParsedScope {
142
146
  rules?: MirrorRules | null
143
147
  caps?: ScopeCaps | null
144
148
  title?: string | null
149
+ wake?: Wake | null
145
150
  incarnation?: string | null
146
151
  }
147
152
 
@@ -1609,7 +1614,7 @@ export class FederatedCore extends RelayCore {
1609
1614
  const was = this.view(before)
1610
1615
  const presence = was.presence !== view.presence
1611
1616
  const status = before.status_state !== after.status_state || before.status_note !== after.status_note
1612
- const other = (["kind", "harness", "model", "cwd", "labels", "title", "tree", "parent_ep", "depth", "rules", "caps", "incarnation"] as const).some(
1617
+ const other = (["kind", "harness", "model", "cwd", "labels", "title", "wake", "tree", "parent_ep", "depth", "rules", "caps", "incarnation"] as const).some(
1613
1618
  (field) => before[field] !== (after as FederatedRow)[field],
1614
1619
  )
1615
1620
  return presence || status || other ? { view, added: false, presence, status } : null
@@ -1682,6 +1687,7 @@ export class FederatedCore extends RelayCore {
1682
1687
  rules: rules === undefined ? row.rules : rules && (rules.in || rules.out) ? JSON.stringify(rules) : null,
1683
1688
  caps,
1684
1689
  title: scope.title !== undefined ? scope.title : fresh ? null : row.title,
1690
+ wake: scope.wake !== undefined ? scope.wake : fresh ? null : row.wake,
1685
1691
  incarnation: scope.incarnation ?? row.incarnation,
1686
1692
  }
1687
1693
  }
@@ -1860,6 +1866,7 @@ function parseScope(view: Partial<MirrorView>): ParsedScope {
1860
1866
  throw new RelayError("too_large", `an endpoint's rules and caps are more than ${SCOPE_BYTES} bytes`)
1861
1867
  if (given("title"))
1862
1868
  out.title = view.title === null ? null : cleanText(typeof view.title === "string" ? view.title.replace(/\s+/g, " ") : view.title, "title", 64) || null
1869
+ if (given("wake")) out.wake = typeof view.wake === "string" && view.wake !== "none" && WAKES.includes(view.wake as Wake) ? (view.wake as Wake) : null
1863
1870
  if (given("incarnation")) {
1864
1871
  if (view.incarnation !== null && (typeof view.incarnation !== "string" || !INCARNATION.test(view.incarnation))) throw bad("incarnation")
1865
1872
  out.incarnation = view.incarnation ?? null
package/src/hub.ts CHANGED
@@ -38,6 +38,7 @@ import {
38
38
  SYSTEM_HANDLE,
39
39
  sameSecret,
40
40
  untilTomorrow,
41
+ type Wake,
41
42
  type XContact,
42
43
  XCounters,
43
44
  type XDelivered,
@@ -104,7 +105,7 @@ export interface GraphNode {
104
105
  status: EndpointView["status"]
105
106
  last_seen: string | null
106
107
  parent: string | null
107
- wake?: string | null
108
+ wake?: Wake | null
108
109
  }
109
110
 
110
111
  /** `spawn`: parent to child; `message`: sender to recipient, with the count and newest send in the graph's window */
@@ -1593,7 +1594,7 @@ export class RelayHub {
1593
1594
  /** a read-only graph for a dashboard: listed endpoints, spawn edges among them, and message counts per sender and recipient; never a body */
1594
1595
  graph(minutes = GRAPH_MINUTES): HubGraph {
1595
1596
  const window = Math.min(Math.max(1, Math.floor(Number.isFinite(minutes) ? minutes : GRAPH_MINUTES)), GRAPH_MINUTES_MAX)
1596
- const endpoints = this.relay.list() as (EndpointView & { wake?: string | null })[]
1597
+ const endpoints = this.relay.list()
1597
1598
  const byId = new Map(endpoints.map((e) => [e.id, e.address]))
1598
1599
  const listed = new Set(byId.values())
1599
1600
  const nodes: GraphNode[] = endpoints.map((e) => ({