@serfab/cadre-core 0.9.0 → 0.11.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.
- package/README.md +255 -253
- package/dist/bootstrap-peer-store-file.d.ts +13 -0
- package/dist/bootstrap-peer-store-file.js +42 -0
- package/dist/bootstrap-peer-store-file.js.map +1 -0
- package/dist/bootstrap-peer-store.d.ts +73 -0
- package/dist/bootstrap-peer-store.js +128 -0
- package/dist/bootstrap-peer-store.js.map +1 -0
- package/dist/cadre-node.d.ts +1121 -81
- package/dist/cadre-node.js +2276 -262
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-authorization.d.ts +93 -0
- package/dist/control-authorization.js +57 -0
- package/dist/control-authorization.js.map +1 -0
- package/dist/control-cohort.d.ts +26 -0
- package/dist/control-cohort.js +26 -0
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +959 -54
- package/dist/control-database.js +1421 -148
- package/dist/control-database.js.map +1 -1
- package/dist/control-formation-recorder.d.ts +90 -10
- package/dist/control-formation-recorder.js +130 -14
- package/dist/control-formation-recorder.js.map +1 -1
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +651 -72
- package/dist/control-schema.js.map +1 -1
- package/dist/control-stream.d.ts +38 -4
- package/dist/control-stream.js +70 -4
- package/dist/control-stream.js.map +1 -1
- package/dist/control-write-retry.d.ts +161 -0
- package/dist/control-write-retry.js +412 -0
- package/dist/control-write-retry.js.map +1 -0
- package/dist/delegate-admission.d.ts +134 -0
- package/dist/delegate-admission.js +244 -0
- package/dist/delegate-admission.js.map +1 -0
- package/dist/device-token.d.ts +11 -11
- package/dist/device-token.js +14 -13
- package/dist/device-token.js.map +1 -1
- package/dist/ed25519-key.d.ts +26 -0
- package/dist/ed25519-key.js +56 -1
- package/dist/ed25519-key.js.map +1 -1
- package/dist/file-durable-slot.d.ts +20 -0
- package/dist/file-durable-slot.js +53 -0
- package/dist/file-durable-slot.js.map +1 -0
- package/dist/formation-approval.d.ts +157 -0
- package/dist/formation-approval.js +375 -0
- package/dist/formation-approval.js.map +1 -0
- package/dist/fs-atomic.d.ts +38 -0
- package/dist/fs-atomic.js +97 -0
- package/dist/fs-atomic.js.map +1 -0
- package/dist/identity-key.d.ts +49 -0
- package/dist/identity-key.js +81 -0
- package/dist/identity-key.js.map +1 -0
- package/dist/index.d.ts +17 -7
- package/dist/index.js +40 -6
- package/dist/index.js.map +1 -1
- package/dist/key-store-file.d.ts +2 -24
- package/dist/key-store-file.js +10 -77
- package/dist/key-store-file.js.map +1 -1
- package/dist/membership-connection-gater.d.ts +146 -0
- package/dist/membership-connection-gater.js +180 -0
- package/dist/membership-connection-gater.js.map +1 -0
- package/dist/node-local-snapshot.d.ts +109 -0
- package/dist/node-local-snapshot.js +182 -0
- package/dist/node-local-snapshot.js.map +1 -0
- package/dist/peer-addr-book.d.ts +92 -0
- package/dist/peer-addr-book.js +220 -0
- package/dist/peer-addr-book.js.map +1 -0
- package/dist/peer-authorization.d.ts +135 -18
- package/dist/peer-authorization.js +152 -21
- package/dist/peer-authorization.js.map +1 -1
- package/dist/peer-record.d.ts +21 -8
- package/dist/peer-record.js +26 -10
- package/dist/peer-record.js.map +1 -1
- package/dist/relay-addrs.d.ts +45 -0
- package/dist/relay-addrs.js +103 -0
- package/dist/relay-addrs.js.map +1 -0
- package/dist/relay-reservation.d.ts +266 -0
- package/dist/relay-reservation.js +613 -0
- package/dist/relay-reservation.js.map +1 -0
- package/dist/seed-bootstrap.d.ts +228 -56
- package/dist/seed-bootstrap.js +340 -198
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/seed-trust-policy.d.ts +47 -21
- package/dist/seed-trust-policy.js +24 -15
- package/dist/seed-trust-policy.js.map +1 -1
- package/dist/strand-addr-protocol.d.ts +42 -13
- package/dist/strand-addr-protocol.js +58 -52
- package/dist/strand-addr-protocol.js.map +1 -1
- package/dist/strand-backfill.d.ts +109 -0
- package/dist/strand-backfill.js +279 -0
- package/dist/strand-backfill.js.map +1 -0
- package/dist/strand-cohort.d.ts +4 -37
- package/dist/strand-cohort.js +4 -15
- package/dist/strand-cohort.js.map +1 -1
- package/dist/strand-database.d.ts +11 -16
- package/dist/strand-database.js +19 -7
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-formation-manager.d.ts +36 -7
- package/dist/strand-formation-manager.js +115 -15
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +103 -4
- package/dist/strand-formation-protocol.js +232 -4
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +88 -19
- package/dist/strand-instance-manager.js +178 -34
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-member-registry.d.ts +5 -5
- package/dist/strand-member-registry.js +18 -10
- package/dist/strand-member-registry.js.map +1 -1
- package/dist/strand-membership-writer.d.ts +484 -88
- package/dist/strand-membership-writer.js +751 -128
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-solicitation.d.ts +99 -33
- package/dist/strand-solicitation.js +100 -52
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/strand-transport-key.d.ts +40 -0
- package/dist/strand-transport-key.js +56 -0
- package/dist/strand-transport-key.js.map +1 -0
- package/dist/strand-wake-protocol.d.ts +9 -7
- package/dist/strand-wake-protocol.js +22 -46
- package/dist/strand-wake-protocol.js.map +1 -1
- package/dist/strand-watcher.d.ts +17 -2
- package/dist/strand-watcher.js +47 -3
- package/dist/strand-watcher.js.map +1 -1
- package/dist/trusted-owner-store-file.d.ts +12 -0
- package/dist/trusted-owner-store-file.js +39 -0
- package/dist/trusted-owner-store-file.js.map +1 -0
- package/dist/trusted-owner-store.d.ts +64 -0
- package/dist/trusted-owner-store.js +126 -0
- package/dist/trusted-owner-store.js.map +1 -0
- package/dist/types.d.ts +307 -44
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -1
- package/package.json +20 -8
- package/src/arachnode-stub.ts +159 -159
- package/src/bootstrap-peer-store-file.ts +44 -0
- package/src/bootstrap-peer-store.ts +172 -0
- package/src/cadre-node.ts +5158 -2981
- package/src/canonical-json.ts +30 -30
- package/src/control-authorization.ts +114 -0
- package/src/control-cohort.ts +130 -103
- package/src/control-database.ts +2406 -948
- package/src/control-formation-recorder.ts +305 -151
- package/src/control-schema.ts +651 -72
- package/src/control-stream.ts +205 -128
- package/src/control-write-retry.ts +483 -0
- package/src/delegate-admission.ts +302 -0
- package/src/device-token.ts +94 -89
- package/src/diagnostics/connection-path.ts +277 -277
- package/src/diagnostics/webrtc-turn-tracker.ts +222 -222
- package/src/ed25519-key.ts +66 -1
- package/src/enrollment.ts +199 -199
- package/src/file-durable-slot.ts +61 -0
- package/src/formation-approval.ts +604 -0
- package/src/fs-atomic.ts +107 -0
- package/src/hibernation-manager.ts +437 -437
- package/src/identity-key.ts +109 -0
- package/src/index.ts +137 -5
- package/src/key-store-file.ts +132 -203
- package/src/key-store.ts +99 -99
- package/src/membership-connection-gater.ts +204 -0
- package/src/node-local-snapshot.ts +260 -0
- package/src/peer-addr-book.ts +250 -0
- package/src/peer-authorization.ts +259 -81
- package/src/peer-record.ts +164 -146
- package/src/push-credentials.ts +84 -84
- package/src/push-node.ts +64 -64
- package/src/push-notifier-apns.ts +247 -247
- package/src/push-notifier-fcm.ts +220 -220
- package/src/push-notifier-shared.ts +28 -28
- package/src/push-notifier.ts +52 -52
- package/src/relay-addrs.ts +111 -0
- package/src/relay-reservation.ts +823 -0
- package/src/seed-bootstrap.ts +409 -209
- package/src/seed-trust-policy.ts +140 -107
- package/src/strand-addr-protocol.ts +441 -410
- package/src/strand-backfill.ts +366 -0
- package/src/strand-cohort.ts +38 -77
- package/src/strand-database.ts +202 -204
- package/src/strand-formation-manager.ts +491 -368
- package/src/strand-formation-protocol.ts +692 -391
- package/src/strand-instance-manager.ts +201 -46
- package/src/strand-member-key.ts +39 -39
- package/src/strand-member-registry.ts +182 -177
- package/src/strand-membership-writer.ts +938 -146
- package/src/strand-solicitation.ts +472 -407
- package/src/strand-transport-key.ts +58 -0
- package/src/strand-wake-payload.ts +32 -32
- package/src/strand-wake-protocol.ts +314 -331
- package/src/strand-watcher.ts +314 -251
- package/src/trusted-owner-store-file.ts +41 -0
- package/src/trusted-owner-store.ts +171 -0
- package/src/types.ts +1309 -1032
package/src/seed-trust-policy.ts
CHANGED
|
@@ -1,107 +1,140 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Trust-anchor policy for control-network seeds.
|
|
3
|
-
*
|
|
4
|
-
* A seed carries an ed25519 signature over its body and the `signerKey` that
|
|
5
|
-
* produced it. Verifying that signature only proves the seed is internally
|
|
6
|
-
* consistent — it does NOT prove the signer is an owner, because both the
|
|
7
|
-
* signer key and the seed's own `isOwner` peer flags are attacker-supplied.
|
|
8
|
-
* The trust decision must therefore rest on an anchor that does not come from
|
|
9
|
-
* the seed body:
|
|
10
|
-
*
|
|
11
|
-
* 1.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
*
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Trust-anchor policy for control-network seeds.
|
|
3
|
+
*
|
|
4
|
+
* A seed carries an ed25519 signature over its body and the `signerKey` that
|
|
5
|
+
* produced it. Verifying that signature only proves the seed is internally
|
|
6
|
+
* consistent — it does NOT prove the signer is an owner, because both the
|
|
7
|
+
* signer key and the seed's own `isOwner` peer flags are attacker-supplied.
|
|
8
|
+
* The trust decision must therefore rest on an anchor that does not come from
|
|
9
|
+
* the seed body:
|
|
10
|
+
*
|
|
11
|
+
* 1. Anchored — keys in the receiver's NODE-LOCAL `TrustedOwnerStore`: the
|
|
12
|
+
* non-replicated, per-party record of owner keys established out of band
|
|
13
|
+
* (founding the party, the `CadreInvite` that enrolled this node, an
|
|
14
|
+
* operator pin). Deliberately NOT the replicated `CadreControl.OwnerKey`
|
|
15
|
+
* table — any connecting node can genesis-insert its own key there and let
|
|
16
|
+
* it replicate, so that table can be made to say "yes" by a stranger.
|
|
17
|
+
* 2. Pinned out-of-band — keys handed to the node for this seed only (carried
|
|
18
|
+
* by a `CadreInvite.ownerKeys`, or pinned by an operator) without having
|
|
19
|
+
* been anchored yet.
|
|
20
|
+
* 3. TOFU (opt-in) — an explicit confirmation callback invoked on first sight
|
|
21
|
+
* of an unknown signer key. Interactive hosts only; off by default.
|
|
22
|
+
*
|
|
23
|
+
* Secure default (`anchoredTrustPolicy`): a node with an empty anchor and no
|
|
24
|
+
* pinned keys rejects the seed — a seed can no longer vouch for its own signer,
|
|
25
|
+
* and neither can a polluted replicated table.
|
|
26
|
+
*
|
|
27
|
+
* A key accepted via anchor 2 or 3 is reported back through
|
|
28
|
+
* {@link SeedTrustDecision.anchorAs} so `applySeed` can persist it into the
|
|
29
|
+
* node-local anchor, and later seeds from the same owner are accepted without
|
|
30
|
+
* re-supplying the invite/confirmation.
|
|
31
|
+
*/
|
|
32
|
+
import type { TrustSource } from './trusted-owner-store.js';
|
|
33
|
+
|
|
34
|
+
export interface SeedTrustContext {
|
|
35
|
+
/** Party the seed claims to belong to. */
|
|
36
|
+
partyId: string;
|
|
37
|
+
/** ed25519 base64url signer key — already signature-verified by `applySeed`. */
|
|
38
|
+
signerKey: string;
|
|
39
|
+
/**
|
|
40
|
+
* The receiver's anchored owner keys, sourced from its node-local
|
|
41
|
+
* `TrustedOwnerStore` — NOT from the seed, and NOT from the replicated
|
|
42
|
+
* `OwnerKey` table. Empty for a node whose anchor was never seeded.
|
|
43
|
+
*/
|
|
44
|
+
knownOwnerKeys: ReadonlySet<string>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface SeedTrustDecision {
|
|
48
|
+
/** Whether the signer key is trusted. */
|
|
49
|
+
trusted: boolean;
|
|
50
|
+
/** Human-readable reason, surfaced as the seed-apply error when not trusted. */
|
|
51
|
+
reason?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Set when the key was trusted via an anchor OUTSIDE the node-local store (a
|
|
54
|
+
* pinned key, a TOFU confirmation): the provenance to record it under, so
|
|
55
|
+
* `applySeed` persists it and the next seed from that owner is anchored
|
|
56
|
+
* without re-supplying the pin. Omitted when the key was already anchored
|
|
57
|
+
* (nothing to persist) or not trusted at all.
|
|
58
|
+
*/
|
|
59
|
+
anchorAs?: Exclude<TrustSource, 'genesis'>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Decides whether a signature-verified seed's signer key should be trusted.
|
|
64
|
+
* May be synchronous (anchored/pinned) or asynchronous (TOFU confirmation).
|
|
65
|
+
*/
|
|
66
|
+
export interface SeedTrustPolicy {
|
|
67
|
+
evaluate(ctx: SeedTrustContext): Promise<SeedTrustDecision> | SeedTrustDecision;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Default policy: trust only keys already in the receiver's node-local
|
|
72
|
+
* trusted-owner anchor. A node whose anchor was never seeded (no genesis, no
|
|
73
|
+
* invite pin, no operator pin) rejects every seed.
|
|
74
|
+
*/
|
|
75
|
+
export function anchoredTrustPolicy(): SeedTrustPolicy {
|
|
76
|
+
return {
|
|
77
|
+
evaluate({ signerKey, knownOwnerKeys }) {
|
|
78
|
+
if (knownOwnerKeys.has(signerKey)) {
|
|
79
|
+
return { trusted: true };
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
trusted: false,
|
|
83
|
+
reason: 'Signer key is not an anchored owner (anchored trust policy)',
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Cold-start policy: trust anchored keys plus a set pinned out-of-band
|
|
91
|
+
* (typically `CadreInvite.ownerKeys` or operator config). Lets an unenrolled
|
|
92
|
+
* invitee accept its first seed without the seed vouching for itself.
|
|
93
|
+
*
|
|
94
|
+
* @param anchorAs - provenance under which a pin-only acceptance is persisted
|
|
95
|
+
* into the node-local anchor ('invite' by default — the invite-redemption
|
|
96
|
+
* case; pass 'operator' for an operator-supplied pin).
|
|
97
|
+
*/
|
|
98
|
+
export function pinnedKeyTrustPolicy(
|
|
99
|
+
pinned: Iterable<string>,
|
|
100
|
+
anchorAs: Exclude<TrustSource, 'genesis'> = 'invite'
|
|
101
|
+
): SeedTrustPolicy {
|
|
102
|
+
const pinnedSet = new Set(pinned);
|
|
103
|
+
return {
|
|
104
|
+
evaluate({ signerKey, knownOwnerKeys }) {
|
|
105
|
+
if (knownOwnerKeys.has(signerKey)) {
|
|
106
|
+
return { trusted: true };
|
|
107
|
+
}
|
|
108
|
+
if (pinnedSet.has(signerKey)) {
|
|
109
|
+
return { trusted: true, anchorAs };
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
trusted: false,
|
|
113
|
+
reason: 'Signer key is neither an anchored nor a pinned owner (pinned-key trust policy)',
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Opt-in interactive policy: trust keys already in the node-local anchor, and
|
|
121
|
+
* on an unknown key invoke `confirm` (e.g. a trust-circle UI prompt). The key is
|
|
122
|
+
* trusted iff `confirm` resolves true, and a confirmed key is persisted into the
|
|
123
|
+
* anchor as an 'operator' pin (a human at the console is the same provenance as
|
|
124
|
+
* an explicit operator pin) so the prompt is not repeated. Not enabled by default.
|
|
125
|
+
*/
|
|
126
|
+
export function tofuTrustPolicy(
|
|
127
|
+
confirm: (ctx: SeedTrustContext) => Promise<boolean>
|
|
128
|
+
): SeedTrustPolicy {
|
|
129
|
+
return {
|
|
130
|
+
async evaluate(ctx) {
|
|
131
|
+
if (ctx.knownOwnerKeys.has(ctx.signerKey)) {
|
|
132
|
+
return { trusted: true };
|
|
133
|
+
}
|
|
134
|
+
const accepted = await confirm(ctx);
|
|
135
|
+
return accepted
|
|
136
|
+
? { trusted: true, anchorAs: 'operator' }
|
|
137
|
+
: { trusted: false, reason: 'TOFU confirmation declined for unknown signer key' };
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|