@serfab/cadre-core 1.13.0 → 1.15.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 +293 -274
- package/dist/cadre-invite-protocol.d.ts +383 -0
- package/dist/cadre-invite-protocol.js +774 -0
- package/dist/cadre-invite-protocol.js.map +1 -0
- package/dist/cadre-join-request.d.ts +42 -0
- package/dist/cadre-join-request.js +144 -0
- package/dist/cadre-join-request.js.map +1 -0
- package/dist/cadre-node.d.ts +849 -210
- package/dist/cadre-node.js +1574 -374
- package/dist/cadre-node.js.map +1 -1
- package/dist/claim-proof.d.ts +45 -0
- package/dist/claim-proof.js +132 -0
- package/dist/claim-proof.js.map +1 -0
- package/dist/control-authorization.d.ts +80 -19
- package/dist/control-authorization.js +55 -13
- package/dist/control-authorization.js.map +1 -1
- package/dist/control-cohort.js +1 -1
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +605 -108
- package/dist/control-database.js +1299 -280
- package/dist/control-database.js.map +1 -1
- package/dist/control-protocol-guard.d.ts +142 -0
- package/dist/control-protocol-guard.js +293 -0
- package/dist/control-protocol-guard.js.map +1 -0
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +817 -1067
- package/dist/control-schema.js.map +1 -1
- package/dist/control-stream.d.ts +4 -0
- package/dist/control-stream.js +22 -7
- package/dist/control-stream.js.map +1 -1
- package/dist/delegate-admission.d.ts +1 -1
- package/dist/delegate-admission.js +1 -1
- package/dist/device-token.d.ts +11 -9
- package/dist/device-token.js +14 -12
- package/dist/device-token.js.map +1 -1
- package/dist/ed25519-key.d.ts +22 -9
- package/dist/ed25519-key.js +47 -10
- package/dist/ed25519-key.js.map +1 -1
- package/dist/fetch-impl.d.ts +12 -0
- package/dist/fetch-impl.js +23 -0
- package/dist/fetch-impl.js.map +1 -0
- package/dist/file-durable-slot.js +2 -1
- package/dist/file-durable-slot.js.map +1 -1
- package/dist/file-safe-name.d.ts +25 -0
- package/dist/file-safe-name.js +29 -0
- package/dist/file-safe-name.js.map +1 -0
- package/dist/formation-approval.js +5 -11
- package/dist/formation-approval.js.map +1 -1
- package/dist/fs-atomic.d.ts +0 -19
- package/dist/fs-atomic.js +3 -24
- package/dist/fs-atomic.js.map +1 -1
- package/dist/index.d.ts +22 -10
- package/dist/index.js +54 -11
- package/dist/index.js.map +1 -1
- package/dist/invitation-bootstrap.d.ts +50 -12
- package/dist/invitation-bootstrap.js +76 -13
- package/dist/invitation-bootstrap.js.map +1 -1
- package/dist/joined-strand-store.d.ts +7 -0
- package/dist/joined-strand-store.js +9 -0
- package/dist/joined-strand-store.js.map +1 -1
- package/dist/key-store-file.js +2 -1
- package/dist/key-store-file.js.map +1 -1
- package/dist/link-budget.d.ts +25 -33
- package/dist/link-budget.js +25 -35
- package/dist/link-budget.js.map +1 -1
- package/dist/machine-removal.d.ts +78 -0
- package/dist/machine-removal.js +166 -0
- package/dist/machine-removal.js.map +1 -0
- package/dist/membership-connection-gater.d.ts +191 -151
- package/dist/membership-connection-gater.js +236 -173
- package/dist/membership-connection-gater.js.map +1 -1
- package/dist/node-claim-payload.d.ts +74 -0
- package/dist/node-claim-payload.js +224 -0
- package/dist/node-claim-payload.js.map +1 -0
- package/dist/node-default-transports.d.ts +27 -0
- package/dist/node-default-transports.js +35 -0
- package/dist/node-default-transports.js.map +1 -0
- package/dist/node-transports.d.ts +30 -0
- package/dist/node-transports.js +40 -0
- package/dist/node-transports.js.map +1 -0
- package/dist/owner-anchor-sync.d.ts +22 -0
- package/dist/owner-anchor-sync.js +143 -0
- package/dist/owner-anchor-sync.js.map +1 -0
- package/dist/peer-authorization.d.ts +113 -18
- package/dist/peer-authorization.js +225 -29
- package/dist/peer-authorization.js.map +1 -1
- package/dist/peer-dial.d.ts +143 -27
- package/dist/peer-dial.js +276 -31
- package/dist/peer-dial.js.map +1 -1
- package/dist/peer-join-backfill.d.ts +26 -2
- package/dist/peer-join-backfill.js +60 -12
- package/dist/peer-join-backfill.js.map +1 -1
- package/dist/peer-record.d.ts +17 -52
- package/dist/peer-record.js +20 -58
- package/dist/peer-record.js.map +1 -1
- package/dist/pending-join-runner.d.ts +66 -58
- package/dist/pending-join-runner.js +136 -145
- package/dist/pending-join-runner.js.map +1 -1
- package/dist/primary-lan-address.d.ts +8 -0
- package/dist/primary-lan-address.js +46 -0
- package/dist/primary-lan-address.js.map +1 -0
- package/dist/provider/client.d.ts +131 -0
- package/dist/provider/client.js +226 -0
- package/dist/provider/client.js.map +1 -0
- package/dist/provider/descriptor.d.ts +41 -0
- package/dist/provider/descriptor.js +103 -0
- package/dist/provider/descriptor.js.map +1 -0
- package/dist/provider/index.d.ts +9 -0
- package/dist/provider/index.js +10 -0
- package/dist/provider/index.js.map +1 -0
- package/dist/provider/oauth.d.ts +125 -0
- package/dist/provider/oauth.js +199 -0
- package/dist/provider/oauth.js.map +1 -0
- package/dist/provider/rent-node.d.ts +101 -0
- package/dist/provider/rent-node.js +220 -0
- package/dist/provider/rent-node.js.map +1 -0
- package/dist/push-fanout.d.ts +8 -2
- package/dist/push-fanout.js +8 -2
- package/dist/push-fanout.js.map +1 -1
- package/dist/relay-addrs.d.ts +9 -4
- package/dist/relay-addrs.js +9 -4
- package/dist/relay-addrs.js.map +1 -1
- package/dist/relay-reservation.d.ts +51 -16
- package/dist/relay-reservation.js +107 -24
- package/dist/relay-reservation.js.map +1 -1
- package/dist/seed-bootstrap.d.ts +165 -123
- package/dist/seed-bootstrap.js +313 -275
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/seed-trust-policy.d.ts +98 -37
- package/dist/seed-trust-policy.js +188 -2
- package/dist/seed-trust-policy.js.map +1 -1
- package/dist/strand-addr-protocol.d.ts +24 -26
- package/dist/strand-addr-protocol.js +19 -26
- package/dist/strand-addr-protocol.js.map +1 -1
- package/dist/strand-commit-durability.d.ts +54 -0
- package/dist/strand-commit-durability.js +74 -0
- package/dist/strand-commit-durability.js.map +1 -0
- package/dist/strand-database.d.ts +23 -8
- package/dist/strand-database.js +41 -13
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +7 -1
- package/dist/strand-first-sync-gate.js +7 -1
- package/dist/strand-first-sync-gate.js.map +1 -1
- package/dist/strand-formation-protocol.js +5 -2
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-fret-addrs.d.ts +19 -1
- package/dist/strand-fret-addrs.js +27 -9
- package/dist/strand-fret-addrs.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +81 -19
- package/dist/strand-instance-manager.js +216 -105
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-move.d.ts +124 -0
- package/dist/strand-move.js +438 -0
- package/dist/strand-move.js.map +1 -0
- package/dist/strand-network-config.js +7 -6
- package/dist/strand-network-config.js.map +1 -1
- package/dist/strand-peer-redial.d.ts +113 -0
- package/dist/strand-peer-redial.js +236 -0
- package/dist/strand-peer-redial.js.map +1 -0
- package/dist/strand-revocation-enforcer.d.ts +11 -11
- package/dist/strand-revocation-enforcer.js +11 -11
- package/dist/strand-wake-protocol.d.ts +13 -16
- package/dist/strand-wake-protocol.js +23 -27
- package/dist/strand-wake-protocol.js.map +1 -1
- package/dist/trusted-owner-store.d.ts +35 -5
- package/dist/trusted-owner-store.js +50 -8
- package/dist/trusted-owner-store.js.map +1 -1
- package/dist/types.d.ts +512 -89
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -1
- package/package.json +19 -10
- package/src/cadre-invite-protocol.ts +1052 -0
- package/src/cadre-join-request.ts +167 -0
- package/src/cadre-node.ts +1703 -386
- package/src/claim-proof.ts +147 -0
- package/src/control-authorization.ts +203 -117
- package/src/control-cohort.ts +1 -1
- package/src/control-database.ts +4663 -3453
- package/src/control-protocol-guard.ts +348 -0
- package/src/control-schema.ts +828 -1078
- package/src/control-stream.ts +26 -7
- package/src/delegate-admission.ts +1 -1
- package/src/device-token.ts +14 -10
- package/src/ed25519-key.ts +47 -10
- package/src/fetch-impl.ts +23 -0
- package/src/file-durable-slot.ts +64 -63
- package/src/file-safe-name.ts +32 -0
- package/src/formation-approval.ts +604 -610
- package/src/fs-atomic.ts +92 -117
- package/src/index.ts +789 -648
- package/src/invitation-bootstrap.ts +91 -13
- package/src/joined-strand-store.ts +508 -498
- package/src/key-store-file.ts +142 -141
- package/src/link-budget.ts +25 -36
- package/src/machine-removal.ts +216 -0
- package/src/membership-connection-gater.ts +259 -191
- package/src/node-claim-payload.ts +259 -0
- package/src/node-default-transports.ts +38 -0
- package/src/node-transports.ts +49 -0
- package/src/owner-anchor-sync.ts +171 -0
- package/src/peer-authorization.ts +258 -29
- package/src/peer-dial.ts +604 -315
- package/src/peer-join-backfill.ts +62 -11
- package/src/peer-record.ts +159 -197
- package/src/pending-join-runner.ts +729 -735
- package/src/primary-lan-address.ts +47 -0
- package/src/provider/client.ts +326 -0
- package/src/provider/descriptor.ts +129 -0
- package/src/provider/index.ts +59 -0
- package/src/provider/oauth.ts +285 -0
- package/src/provider/rent-node.ts +275 -0
- package/src/push-fanout.ts +8 -2
- package/src/relay-addrs.ts +9 -4
- package/src/relay-reservation.ts +1211 -1121
- package/src/seed-bootstrap.ts +1502 -1448
- package/src/seed-trust-policy.ts +353 -140
- package/src/strand-addr-protocol.ts +26 -35
- package/src/strand-commit-durability.ts +116 -0
- package/src/strand-database.ts +46 -14
- package/src/strand-first-sync-gate.ts +7 -1
- package/src/strand-formation-protocol.ts +1039 -1036
- package/src/strand-fret-addrs.ts +179 -145
- package/src/strand-instance-manager.ts +2026 -1883
- package/src/strand-move.ts +585 -0
- package/src/strand-network-config.ts +7 -6
- package/src/strand-peer-redial.ts +307 -0
- package/src/strand-revocation-enforcer.ts +11 -11
- package/src/strand-wake-protocol.ts +23 -30
- package/src/trusted-owner-store.ts +242 -171
- package/src/types.ts +2687 -2242
|
@@ -1,23 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Which of the inviting party's
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Which of the inviting party's machines an invitation names, so a joiner can still form or
|
|
3
|
+
* join while the machine that minted it is offline: an open strand invitation
|
|
4
|
+
* (`CadreNode.createOpenInvitation`, which puts the minting machine's own addresses first
|
|
5
|
+
* itself) and a cadre invitation ({@link selectCadreInvitationMembers}). Also how far a cadre
|
|
6
|
+
* invitation reaches once its minting machine is gone ({@link cadreInvitationReach}).
|
|
5
7
|
*/
|
|
6
8
|
|
|
9
|
+
import { classifyDialAddress, destinationPeerIdOf, type DialAddressKind } from './node-claim-payload.js';
|
|
10
|
+
import type { CadreInvitationReach } from './types.js';
|
|
11
|
+
|
|
7
12
|
/**
|
|
8
13
|
* At most this many of the party's other machines are named, each with at most
|
|
9
14
|
* {@link INVITATION_ADDRS_PER_SIBLING} addresses: 12 extra addresses of roughly 100–200
|
|
10
15
|
* characters, base64url-encoded into an invitation shared as text.
|
|
11
16
|
*
|
|
12
|
-
* NOTE:
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
+
* NOTE: a cadre invitation, which may be carried in a QR code, is capped harder
|
|
18
|
+
* ({@link CADRE_INVITATION_MAX_ADDRS}); an open strand invitation keeps these caps. If open
|
|
19
|
+
* invitations are ever carried in a QR code too, cap them the same way.
|
|
20
|
+
* NOTE: for an open strand invitation the per-machine cap keeps the record's order (relay first,
|
|
21
|
+
* then direct addresses as the machine published them, loopback included); a cadre invitation
|
|
22
|
+
* ranks them first. If an open invitation's sibling is seen to have its reachable address cut,
|
|
23
|
+
* rank the same way.
|
|
17
24
|
*/
|
|
18
25
|
export const INVITATION_SIBLING_MACHINES = 3;
|
|
19
26
|
export const INVITATION_ADDRS_PER_SIBLING = 4;
|
|
20
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Most addresses a cadre invitation names in total, so its text fits one QR code. Measured
|
|
30
|
+
* with three owner keys: 2,206 characters encoded at 6 relayed addresses of about 155
|
|
31
|
+
* characters (the worst case, since ranking puts relayed addresses first), 1,972 with relayed
|
|
32
|
+
* and direct WebSocket addresses alternating, against 2,331 bytes in the largest QR code at
|
|
33
|
+
* error-correction level M (2,953 at L). Each further address costs about 170 characters, each
|
|
34
|
+
* further owner key about 60.
|
|
35
|
+
*/
|
|
36
|
+
export const CADRE_INVITATION_MAX_ADDRS = 6;
|
|
37
|
+
|
|
38
|
+
/** Most addresses a cadre invitation names for each of the party's other machines. */
|
|
39
|
+
export const CADRE_INVITATION_ADDRS_PER_SIBLING = 2;
|
|
40
|
+
|
|
21
41
|
/** One other machine of the party whose signed address record resolved. */
|
|
22
42
|
export interface InvitationSibling {
|
|
23
43
|
peerId: string;
|
|
@@ -28,13 +48,71 @@ export interface InvitationSibling {
|
|
|
28
48
|
}
|
|
29
49
|
|
|
30
50
|
/**
|
|
31
|
-
* The addresses of the siblings an invitation names
|
|
32
|
-
* now come first, since a live connection is the best evidence that
|
|
33
|
-
* shows only that it was up within the freshness window. Within each
|
|
51
|
+
* The addresses of the siblings an invitation names, at most `perSibling` each. Machines this
|
|
52
|
+
* node is connected to right now come first, since a live connection is the best evidence that
|
|
53
|
+
* a machine is up; a record shows only that it was up within the freshness window. Within each
|
|
54
|
+
* half, newest record first.
|
|
34
55
|
*/
|
|
35
|
-
export function selectInvitationSiblingAddrs(
|
|
56
|
+
export function selectInvitationSiblingAddrs(
|
|
57
|
+
siblings: InvitationSibling[],
|
|
58
|
+
connected: ReadonlySet<string>,
|
|
59
|
+
perSibling: number = INVITATION_ADDRS_PER_SIBLING
|
|
60
|
+
): string[] {
|
|
36
61
|
return [...siblings]
|
|
37
62
|
.sort((a, b) => Number(connected.has(b.peerId)) - Number(connected.has(a.peerId)) || b.updatedAt - a.updatedAt)
|
|
38
63
|
.slice(0, INVITATION_SIBLING_MACHINES)
|
|
39
|
-
.flatMap((sibling) => sibling.addrs.slice(0,
|
|
64
|
+
.flatMap((sibling) => sibling.addrs.slice(0, perSibling));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The `members` of a cadre invitation: the minting machine's own addresses first (at most
|
|
69
|
+
* {@link INVITATION_ADDRS_PER_SIBLING}), then the other machines' in
|
|
70
|
+
* {@link selectInvitationSiblingAddrs} order (at most {@link CADRE_INVITATION_ADDRS_PER_SIBLING}
|
|
71
|
+
* each), the whole list cut to {@link CADRE_INVITATION_MAX_ADDRS}. Each machine's addresses are
|
|
72
|
+
* ranked for a phone before they are cut ({@link rankForPhone}): libp2p reports a machine
|
|
73
|
+
* listening on every interface with its loopback and private addresses ahead of its relayed one.
|
|
74
|
+
*
|
|
75
|
+
* NOTE: accepted tradeoff — with two or more other machines, only the best two addresses of
|
|
76
|
+
* each survive, connected machines first, so a reachable address of a sibling can be cut. Size
|
|
77
|
+
* was weighed over completeness, so the text fits a QR code; revisit if redemptions are seen
|
|
78
|
+
* failing for want of a sibling address the record held.
|
|
79
|
+
*/
|
|
80
|
+
export function selectCadreInvitationMembers(
|
|
81
|
+
own: readonly string[],
|
|
82
|
+
siblings: InvitationSibling[],
|
|
83
|
+
connected: ReadonlySet<string>
|
|
84
|
+
): string[] {
|
|
85
|
+
const ranked = siblings.map((sibling) => ({ ...sibling, addrs: rankForPhone(sibling.addrs) }));
|
|
86
|
+
return [
|
|
87
|
+
...rankForPhone(own).slice(0, INVITATION_ADDRS_PER_SIBLING),
|
|
88
|
+
...selectInvitationSiblingAddrs(ranked, connected, CADRE_INVITATION_ADDRS_PER_SIBLING),
|
|
89
|
+
].slice(0, CADRE_INVITATION_MAX_ADDRS);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Order in which a phone is likeliest to reach an address: from anywhere, on its network, on that machine, not at all. */
|
|
93
|
+
const PHONE_DIAL_RANK: Record<DialAddressKind, number> = { relay: 0, name: 0, public: 0, private: 1, loopback: 2 };
|
|
94
|
+
|
|
95
|
+
/** `addrs` best first for a phone dialing them ({@link PHONE_DIAL_RANK}), ties in their given order; one a phone cannot dial (plain TCP) last. */
|
|
96
|
+
function rankForPhone(addrs: readonly string[]): string[] {
|
|
97
|
+
const rankOf = (addr: string): number => {
|
|
98
|
+
const kind = classifyDialAddress(addr);
|
|
99
|
+
return kind === undefined ? 3 : PHONE_DIAL_RANK[kind];
|
|
100
|
+
};
|
|
101
|
+
return addrs.map((addr) => ({ addr, rank: rankOf(addr) })).sort((a, b) => a.rank - b.rank).map(({ addr }) => addr);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Where a phone could redeem an invitation naming `members` from, judged on the machines other
|
|
106
|
+
* than `issuerPeerId`: in the app flows the minting app is the one closed or in the background
|
|
107
|
+
* when the other app redeems, and two apps on one phone cannot reach each other. An address
|
|
108
|
+
* names its machine by its last `/p2p/`.
|
|
109
|
+
*/
|
|
110
|
+
export function cadreInvitationReach(members: readonly string[], issuerPeerId: string): CadreInvitationReach {
|
|
111
|
+
const others = members.flatMap((addr) => {
|
|
112
|
+
const kind = classifyDialAddress(addr);
|
|
113
|
+
// Classified, so it parses and `destinationPeerIdOf` cannot throw.
|
|
114
|
+
return kind === undefined || destinationPeerIdOf(addr) === issuerPeerId ? [] : [kind];
|
|
115
|
+
});
|
|
116
|
+
if (others.some((kind) => kind === 'relay' || kind === 'name' || kind === 'public')) return 'anywhere';
|
|
117
|
+
return others.length > 0 ? 'local-network' : 'issuer-only';
|
|
40
118
|
}
|