@serfab/cadre-core 0.11.0 → 0.13.0

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.
Files changed (121) hide show
  1. package/README.md +3 -2
  2. package/dist/announce-addrs.d.ts +49 -0
  3. package/dist/announce-addrs.js +78 -0
  4. package/dist/announce-addrs.js.map +1 -0
  5. package/dist/cadre-node.d.ts +607 -53
  6. package/dist/cadre-node.js +1268 -157
  7. package/dist/cadre-node.js.map +1 -1
  8. package/dist/control-database.d.ts +174 -23
  9. package/dist/control-database.js +317 -107
  10. package/dist/control-database.js.map +1 -1
  11. package/dist/control-read-retry.d.ts +103 -0
  12. package/dist/control-read-retry.js +145 -0
  13. package/dist/control-read-retry.js.map +1 -0
  14. package/dist/control-retry.d.ts +101 -0
  15. package/dist/control-retry.js +108 -0
  16. package/dist/control-retry.js.map +1 -0
  17. package/dist/control-schema.d.ts +1 -1
  18. package/dist/control-schema.js +50 -6
  19. package/dist/control-schema.js.map +1 -1
  20. package/dist/control-write-retry.d.ts +59 -35
  21. package/dist/control-write-retry.js +21 -92
  22. package/dist/control-write-retry.js.map +1 -1
  23. package/dist/delegate-admission.d.ts +17 -15
  24. package/dist/delegate-admission.js +17 -15
  25. package/dist/delegate-admission.js.map +1 -1
  26. package/dist/enrolled-machine-store-file.d.ts +13 -0
  27. package/dist/enrolled-machine-store-file.js +41 -0
  28. package/dist/enrolled-machine-store-file.js.map +1 -0
  29. package/dist/enrolled-machine-store.d.ts +81 -0
  30. package/dist/enrolled-machine-store.js +225 -0
  31. package/dist/enrolled-machine-store.js.map +1 -0
  32. package/dist/file-durable-slot.js +5 -3
  33. package/dist/file-durable-slot.js.map +1 -1
  34. package/dist/index.d.ts +10 -6
  35. package/dist/index.js +39 -12
  36. package/dist/index.js.map +1 -1
  37. package/dist/membership-connection-gater.d.ts +226 -26
  38. package/dist/membership-connection-gater.js +316 -30
  39. package/dist/membership-connection-gater.js.map +1 -1
  40. package/dist/node-local-snapshot.d.ts +6 -0
  41. package/dist/node-local-snapshot.js +7 -1
  42. package/dist/node-local-snapshot.js.map +1 -1
  43. package/dist/{strand-backfill.d.ts → peer-join-backfill.d.ts} +49 -20
  44. package/dist/{strand-backfill.js → peer-join-backfill.js} +146 -56
  45. package/dist/peer-join-backfill.js.map +1 -0
  46. package/dist/peer-record.d.ts +26 -0
  47. package/dist/peer-record.js +32 -0
  48. package/dist/peer-record.js.map +1 -1
  49. package/dist/relay-addrs.d.ts +145 -22
  50. package/dist/relay-addrs.js +314 -31
  51. package/dist/relay-addrs.js.map +1 -1
  52. package/dist/relay-reservation.d.ts +20 -15
  53. package/dist/relay-reservation.js +18 -14
  54. package/dist/relay-reservation.js.map +1 -1
  55. package/dist/strand-addr-protocol.js +16 -0
  56. package/dist/strand-addr-protocol.js.map +1 -1
  57. package/dist/strand-database.d.ts +12 -0
  58. package/dist/strand-database.js +16 -0
  59. package/dist/strand-database.js.map +1 -1
  60. package/dist/strand-formation-manager.d.ts +22 -9
  61. package/dist/strand-formation-manager.js +20 -12
  62. package/dist/strand-formation-manager.js.map +1 -1
  63. package/dist/strand-formation-protocol.d.ts +83 -9
  64. package/dist/strand-formation-protocol.js +86 -10
  65. package/dist/strand-formation-protocol.js.map +1 -1
  66. package/dist/strand-instance-manager.d.ts +151 -17
  67. package/dist/strand-instance-manager.js +237 -32
  68. package/dist/strand-instance-manager.js.map +1 -1
  69. package/dist/strand-membership-writer.d.ts +118 -14
  70. package/dist/strand-membership-writer.js +203 -15
  71. package/dist/strand-membership-writer.js.map +1 -1
  72. package/dist/strand-network-config.d.ts +84 -0
  73. package/dist/strand-network-config.js +136 -0
  74. package/dist/strand-network-config.js.map +1 -0
  75. package/dist/strand-revocation-enforcer.d.ts +392 -0
  76. package/dist/strand-revocation-enforcer.js +533 -0
  77. package/dist/strand-revocation-enforcer.js.map +1 -0
  78. package/dist/strand-solicitation.d.ts +10 -3
  79. package/dist/strand-solicitation.js +12 -7
  80. package/dist/strand-solicitation.js.map +1 -1
  81. package/dist/strand-wake-protocol.d.ts +47 -2
  82. package/dist/strand-wake-protocol.js +76 -6
  83. package/dist/strand-wake-protocol.js.map +1 -1
  84. package/dist/strand-watcher.js +6 -1
  85. package/dist/strand-watcher.js.map +1 -1
  86. package/dist/types.d.ts +282 -43
  87. package/dist/types.js +7 -1
  88. package/dist/types.js.map +1 -1
  89. package/package.json +16 -8
  90. package/src/announce-addrs.ts +93 -0
  91. package/src/cadre-node.ts +1366 -171
  92. package/src/control-database.ts +2628 -2406
  93. package/src/control-read-retry.ts +167 -0
  94. package/src/control-retry.ts +190 -0
  95. package/src/control-schema.ts +50 -6
  96. package/src/control-write-retry.ts +30 -130
  97. package/src/delegate-admission.ts +17 -15
  98. package/src/enrolled-machine-store-file.ts +43 -0
  99. package/src/enrolled-machine-store.ts +280 -0
  100. package/src/file-durable-slot.ts +5 -3
  101. package/src/index.ts +477 -407
  102. package/src/membership-connection-gater.ts +539 -204
  103. package/src/node-local-snapshot.ts +13 -1
  104. package/src/peer-addr-book.ts +251 -250
  105. package/src/{strand-backfill.ts → peer-join-backfill.ts} +187 -75
  106. package/src/peer-record.ts +33 -0
  107. package/src/relay-addrs.ts +436 -111
  108. package/src/relay-reservation.ts +828 -823
  109. package/src/strand-addr-protocol.ts +17 -0
  110. package/src/strand-database.ts +17 -0
  111. package/src/strand-formation-manager.ts +511 -491
  112. package/src/strand-formation-protocol.ts +808 -692
  113. package/src/strand-instance-manager.ts +899 -611
  114. package/src/strand-membership-writer.ts +232 -15
  115. package/src/strand-network-config.ts +172 -0
  116. package/src/strand-revocation-enforcer.ts +653 -0
  117. package/src/strand-solicitation.ts +484 -472
  118. package/src/strand-wake-protocol.ts +94 -8
  119. package/src/strand-watcher.ts +319 -314
  120. package/src/types.ts +1554 -1309
  121. package/dist/strand-backfill.js.map +0 -1
package/README.md CHANGED
@@ -168,9 +168,10 @@ The main entry point for cadre participation.
168
168
  | `stop()` | Gracefully disconnect from all networks |
169
169
  | `getStrands()` | Get all active strand instances |
170
170
  | `getStrand(id)` | Get a specific strand instance |
171
- | `addStrand(row)` | Manually add a strand (testing/direct API) |
171
+ | `foundStrand(config)` | **Create a strand**: publish its `Strand` row and start it locally as founder, in one call that is safe to re-run after an interruption. Returns the instance plus the row it actually runs under — for a closed strand read the membership key from there, since a resumed founding keeps the stored key |
172
+ | `addStrand(row)` | Attach only — start a local instance for a row that already exists (the join path; also testing/direct API). Does **not** publish |
172
173
  | `stopStrand(id)` | Stop a strand on this node only (the shared `Strand` row stays; rediscovered on restart) |
173
- | `publishStrand(id, type?, memberKey?)` | Owner-signed `Strand` row insert — makes the strand visible cadre-wide |
174
+ | `publishStrand(id, type?, memberKey?)` | Owner-signed `Strand` row insert — makes the strand visible cadre-wide. Idempotent: a live row with the same `(Type, MemberPrivateKey)` is returned unwritten; different content on the same id throws. Prefer `foundStrand` when creating a strand |
174
175
  | `unpublishStrand(id)` | Owner-signed party-wide removal — deletes this party's `Strand` row; every node stops the strand. Destroys a closed strand's `MemberPrivateKey` |
175
176
  | `getEnrollmentService()` | Access peer enrollment API |
176
177
 
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Translate `network.announceAddrs` / `network.appendAnnounceAddrs` — the operator-facing
3
+ * "advertise these addresses" settings — into the two `@optimystic/db-p2p` `NodeOptions`
4
+ * fields of the same names, which reach libp2p's `addresses.announce` /
5
+ * `addresses.appendAnnounce`.
6
+ *
7
+ * Two jobs, both of which the control node and every strand node need identically, hence
8
+ * one module rather than the same conditional spread written twice:
9
+ *
10
+ * - **Empty means unset.** libp2p treats `announce: []` as "no override", and forwarding
11
+ * `[]` would still be forwarding a field. An empty config array is dropped so it cannot
12
+ * land as an explicit empty announce set.
13
+ * - **Validate the multiaddrs here, at start.** libp2p does NOT validate announce addrs
14
+ * at construction: `AddressManager` stores them as raw strings and only parses them on
15
+ * the first `getAnnounceAddrs()`. A typo therefore produces a node that starts
16
+ * cleanly, then throws `InvalidMultiaddrError` out of every `getMultiaddrs()` call —
17
+ * including an UNHANDLED one from the debounced peer-store update libp2p runs on
18
+ * `transport:listening`. Verified against libp2p's `address-manager` (its constructor
19
+ * does `announce.map(ma => ma.toString())`; `getAnnounceAddrs()` does `multiaddr(a)`).
20
+ * Parsing each entry up front converts that into a loud failure at node start, which is
21
+ * what {@link relayCircuitAddrs} already does for `network.relayAddrs`.
22
+ *
23
+ * Parsing alone is not enough, though: `''` and `'/'` both parse into a component-less
24
+ * multiaddr, and a set holding only those is non-empty by the rule above — so it would
25
+ * replace every advertised address with nothing at all. An entry naming no address is
26
+ * therefore rejected alongside one that fails to parse.
27
+ */
28
+ import type { NetworkConfig } from './types.js';
29
+ /**
30
+ * The announce fields to spread into `createLibp2pNode` options. A field is present
31
+ * only when the operator configured a non-empty list for it, so a node that configures
32
+ * neither passes neither.
33
+ */
34
+ export interface ResolvedAnnounceAddrs {
35
+ announceAddrs?: string[];
36
+ appendAnnounceAddrs?: string[];
37
+ }
38
+ /**
39
+ * Resolve both announce fields off a `NetworkConfig`. Throws — naming the offending
40
+ * config field and entry — when any entry is not a parsable multiaddr.
41
+ */
42
+ export declare function resolveAnnounceAddrs(network: NetworkConfig | undefined): ResolvedAnnounceAddrs;
43
+ /**
44
+ * Whether this node's advertised set will be REPLACED rather than extended — i.e.
45
+ * whether {@link ResolvedAnnounceAddrs.announceAddrs} is in play at all. The single
46
+ * predicate behind `CadreNode.start()`'s operator warning, kept here so the warning
47
+ * and the forwarding agree on what "set" means (non-empty, not merely present).
48
+ */
49
+ export declare function replacesAdvertisedAddrs(network: NetworkConfig | undefined): boolean;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Translate `network.announceAddrs` / `network.appendAnnounceAddrs` — the operator-facing
3
+ * "advertise these addresses" settings — into the two `@optimystic/db-p2p` `NodeOptions`
4
+ * fields of the same names, which reach libp2p's `addresses.announce` /
5
+ * `addresses.appendAnnounce`.
6
+ *
7
+ * Two jobs, both of which the control node and every strand node need identically, hence
8
+ * one module rather than the same conditional spread written twice:
9
+ *
10
+ * - **Empty means unset.** libp2p treats `announce: []` as "no override", and forwarding
11
+ * `[]` would still be forwarding a field. An empty config array is dropped so it cannot
12
+ * land as an explicit empty announce set.
13
+ * - **Validate the multiaddrs here, at start.** libp2p does NOT validate announce addrs
14
+ * at construction: `AddressManager` stores them as raw strings and only parses them on
15
+ * the first `getAnnounceAddrs()`. A typo therefore produces a node that starts
16
+ * cleanly, then throws `InvalidMultiaddrError` out of every `getMultiaddrs()` call —
17
+ * including an UNHANDLED one from the debounced peer-store update libp2p runs on
18
+ * `transport:listening`. Verified against libp2p's `address-manager` (its constructor
19
+ * does `announce.map(ma => ma.toString())`; `getAnnounceAddrs()` does `multiaddr(a)`).
20
+ * Parsing each entry up front converts that into a loud failure at node start, which is
21
+ * what {@link relayCircuitAddrs} already does for `network.relayAddrs`.
22
+ *
23
+ * Parsing alone is not enough, though: `''` and `'/'` both parse into a component-less
24
+ * multiaddr, and a set holding only those is non-empty by the rule above — so it would
25
+ * replace every advertised address with nothing at all. An entry naming no address is
26
+ * therefore rejected alongside one that fails to parse.
27
+ */
28
+ import { multiaddr } from '@multiformats/multiaddr';
29
+ /**
30
+ * Resolve both announce fields off a `NetworkConfig`. Throws — naming the offending
31
+ * config field and entry — when any entry is not a parsable multiaddr.
32
+ */
33
+ export function resolveAnnounceAddrs(network) {
34
+ const announceAddrs = configuredAddrs('network.announceAddrs', network?.announceAddrs);
35
+ const appendAnnounceAddrs = configuredAddrs('network.appendAnnounceAddrs', network?.appendAnnounceAddrs);
36
+ return {
37
+ ...(announceAddrs && { announceAddrs }),
38
+ ...(appendAnnounceAddrs && { appendAnnounceAddrs })
39
+ };
40
+ }
41
+ /**
42
+ * Whether this node's advertised set will be REPLACED rather than extended — i.e.
43
+ * whether {@link ResolvedAnnounceAddrs.announceAddrs} is in play at all. The single
44
+ * predicate behind `CadreNode.start()`'s operator warning, kept here so the warning
45
+ * and the forwarding agree on what "set" means (non-empty, not merely present).
46
+ */
47
+ export function replacesAdvertisedAddrs(network) {
48
+ return (network?.announceAddrs?.length ?? 0) > 0;
49
+ }
50
+ /** The entries to forward for one announce field, or `undefined` when it is unset or empty. */
51
+ function configuredAddrs(field, addrs) {
52
+ if (!addrs || addrs.length === 0) {
53
+ return undefined;
54
+ }
55
+ return addrs.map((addr) => validated(field, addr));
56
+ }
57
+ /** `addr` unchanged, having proved it names a real address — config field named on failure. */
58
+ function validated(field, addr) {
59
+ if (parsed(field, addr).getComponents().length === 0) {
60
+ // `''` and `'/'` PARSE: both yield a component-less multiaddr that stringifies to
61
+ // `/`. Forwarded, they make an announce set that is non-empty but names nothing —
62
+ // which by the replacement rule above costs the node every address it would
63
+ // otherwise advertise, silently. A templated `cadre.yaml` whose address variable went
64
+ // unsubstituted is the realistic way in, so it is rejected rather than forwarded.
65
+ throw new Error(`${field} entry names no address: ${JSON.stringify(addr)}`);
66
+ }
67
+ return addr;
68
+ }
69
+ /** `addr` as a multiaddr, with the config field named on a parse failure. */
70
+ function parsed(field, addr) {
71
+ try {
72
+ return multiaddr(addr);
73
+ }
74
+ catch (err) {
75
+ throw new Error(`${field} entry is not a valid multiaddr: ${addr}`, { cause: err });
76
+ }
77
+ }
78
+ //# sourceMappingURL=announce-addrs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"announce-addrs.js","sourceRoot":"","sources":["../src/announce-addrs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,SAAS,EAAkB,MAAM,yBAAyB,CAAC;AAapE;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAkC;IACrE,MAAM,aAAa,GAAG,eAAe,CAAC,uBAAuB,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IACvF,MAAM,mBAAmB,GAAG,eAAe,CAAC,6BAA6B,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACzG,OAAO;QACL,GAAG,CAAC,aAAa,IAAI,EAAE,aAAa,EAAE,CAAC;QACvC,GAAG,CAAC,mBAAmB,IAAI,EAAE,mBAAmB,EAAE,CAAC;KACpD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAkC;IACxE,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AACnD,CAAC;AAED,+FAA+F;AAC/F,SAAS,eAAe,CAAC,KAAa,EAAE,KAAoC;IAC1E,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,+FAA+F;AAC/F,SAAS,SAAS,CAAC,KAAa,EAAE,IAAY;IAC5C,IAAI,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,kFAAkF;QAClF,kFAAkF;QAClF,4EAA4E;QAC5E,sFAAsF;QACtF,kFAAkF;QAClF,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,4BAA4B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6EAA6E;AAC7E,SAAS,MAAM,CAAC,KAAa,EAAE,IAAY;IACzC,IAAI,CAAC;QACH,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,oCAAoC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACtF,CAAC;AACH,CAAC"}