@serfab/cadre-core 1.16.0 → 1.17.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 +1 -1
- package/dist/bootstrap-peer-store-file.js +1 -1
- package/dist/bootstrap-peer-store.d.ts +1 -1
- package/dist/bootstrap-peer-store.js +4 -4
- package/dist/cadre-invite-protocol.d.ts +55 -138
- package/dist/cadre-invite-protocol.js +94 -449
- package/dist/cadre-invite-protocol.js.map +1 -1
- package/dist/cadre-join-request.d.ts +15 -2
- package/dist/cadre-join-request.js +22 -3
- package/dist/cadre-join-request.js.map +1 -1
- package/dist/cadre-node.d.ts +530 -247
- package/dist/cadre-node.js +1046 -525
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-authorization.d.ts +36 -14
- package/dist/control-authorization.js +20 -3
- package/dist/control-authorization.js.map +1 -1
- package/dist/control-cohort.d.ts +22 -23
- package/dist/control-cohort.js +24 -24
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +416 -136
- package/dist/control-database.js +757 -378
- package/dist/control-database.js.map +1 -1
- package/dist/control-protocol-guard.d.ts +5 -4
- package/dist/control-protocol-guard.js +6 -3
- package/dist/control-protocol-guard.js.map +1 -1
- package/dist/control-schema-version.d.ts +80 -0
- package/dist/control-schema-version.js +203 -0
- package/dist/control-schema-version.js.map +1 -0
- package/dist/control-schema.d.ts +45 -5
- package/dist/control-schema.js +254 -70
- package/dist/control-schema.js.map +1 -1
- package/dist/control-write-retry.d.ts +5 -5
- package/dist/control-write-retry.js +10 -8
- package/dist/control-write-retry.js.map +1 -1
- package/dist/delegate-admission.d.ts +13 -0
- package/dist/delegate-admission.js +27 -0
- package/dist/delegate-admission.js.map +1 -1
- package/dist/ed25519-key.d.ts +10 -7
- package/dist/ed25519-key.js +23 -20
- package/dist/ed25519-key.js.map +1 -1
- package/dist/edge-node/config.d.ts +122 -0
- package/dist/edge-node/config.js +199 -0
- package/dist/edge-node/config.js.map +1 -0
- package/dist/edge-node/dissolve.d.ts +95 -0
- package/dist/edge-node/dissolve.js +184 -0
- package/dist/edge-node/dissolve.js.map +1 -0
- package/dist/edge-node/edge-join.d.ts +44 -0
- package/dist/edge-node/edge-join.js +227 -0
- package/dist/edge-node/edge-join.js.map +1 -0
- package/dist/edge-node/edge-node.d.ts +295 -0
- package/dist/edge-node/edge-node.js +704 -0
- package/dist/edge-node/edge-node.js.map +1 -0
- package/dist/edge-node/index.d.ts +18 -0
- package/dist/edge-node/index.js +18 -0
- package/dist/edge-node/index.js.map +1 -0
- package/dist/edge-node/join-credential.d.ts +11 -0
- package/dist/edge-node/join-credential.js +11 -0
- package/dist/edge-node/join-credential.js.map +1 -0
- package/dist/edge-node/lazy-raw-storage.d.ts +40 -0
- package/dist/edge-node/lazy-raw-storage.js +134 -0
- package/dist/edge-node/lazy-raw-storage.js.map +1 -0
- package/dist/edge-node/node-local.d.ts +60 -0
- package/dist/edge-node/node-local.js +58 -0
- package/dist/edge-node/node-local.js.map +1 -0
- package/dist/edge-node/options.d.ts +83 -0
- package/dist/edge-node/options.js +110 -0
- package/dist/edge-node/options.js.map +1 -0
- package/dist/edge-node/owner-grant.d.ts +41 -0
- package/dist/edge-node/owner-grant.js +38 -0
- package/dist/edge-node/owner-grant.js.map +1 -0
- package/dist/edge-node/platform.d.ts +140 -0
- package/dist/edge-node/platform.js +12 -0
- package/dist/edge-node/platform.js.map +1 -0
- package/dist/edge-node/strand-move.d.ts +115 -0
- package/dist/edge-node/strand-move.js +223 -0
- package/dist/edge-node/strand-move.js.map +1 -0
- package/dist/edge-node/strands.d.ts +28 -0
- package/dist/edge-node/strands.js +60 -0
- package/dist/edge-node/strands.js.map +1 -0
- package/dist/index.d.ts +16 -7
- package/dist/index.js +26 -7
- package/dist/index.js.map +1 -1
- package/dist/joined-strand-store.d.ts +3 -3
- package/dist/joined-strand-store.js +3 -3
- package/dist/joined-strand-store.js.map +1 -1
- package/dist/key-store.d.ts +9 -4
- package/dist/key-store.js +9 -4
- package/dist/key-store.js.map +1 -1
- package/dist/machine-removal.d.ts +19 -39
- package/dist/machine-removal.js +24 -98
- package/dist/machine-removal.js.map +1 -1
- package/dist/member-redemption.d.ts +250 -0
- package/dist/member-redemption.js +485 -0
- package/dist/member-redemption.js.map +1 -0
- package/dist/owner-anchor-sync.d.ts +4 -4
- package/dist/owner-anchor-sync.js +16 -15
- package/dist/owner-anchor-sync.js.map +1 -1
- package/dist/owner-grant-protocol.d.ts +247 -0
- package/dist/owner-grant-protocol.js +330 -0
- package/dist/owner-grant-protocol.js.map +1 -0
- package/dist/owner-key-export.d.ts +70 -0
- package/dist/owner-key-export.js +279 -0
- package/dist/owner-key-export.js.map +1 -0
- package/dist/owner-key-flows.d.ts +55 -0
- package/dist/owner-key-flows.js +60 -0
- package/dist/owner-key-flows.js.map +1 -0
- package/dist/owner-key-store.d.ts +31 -0
- package/dist/owner-key-store.js +81 -0
- package/dist/owner-key-store.js.map +1 -0
- package/dist/owner-keys.d.ts +78 -0
- package/dist/owner-keys.js +133 -0
- package/dist/owner-keys.js.map +1 -0
- package/dist/owner-signer.d.ts +54 -0
- package/dist/owner-signer.js +51 -0
- package/dist/owner-signer.js.map +1 -0
- package/dist/peer-authorization.d.ts +83 -18
- package/dist/peer-authorization.js +123 -53
- package/dist/peer-authorization.js.map +1 -1
- package/dist/provider/rent-node.js +1 -1
- package/dist/provider/rent-node.js.map +1 -1
- package/dist/seed-bootstrap.d.ts +131 -109
- package/dist/seed-bootstrap.js +260 -248
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/seed-trust-policy.js +4 -4
- package/dist/strand-addr-protocol.d.ts +4 -1
- package/dist/strand-addr-protocol.js +8 -2
- package/dist/strand-addr-protocol.js.map +1 -1
- package/dist/strand-cohort.d.ts +3 -0
- package/dist/strand-cohort.js.map +1 -1
- package/dist/strand-database.d.ts +1 -0
- package/dist/strand-database.js +3 -0
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +4 -3
- package/dist/strand-first-sync-gate.js +4 -3
- package/dist/strand-first-sync-gate.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +1 -1
- package/dist/strand-membership-writer.d.ts +13 -2
- package/dist/strand-membership-writer.js +52 -16
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-move.d.ts +6 -5
- package/dist/strand-move.js +31 -30
- package/dist/strand-move.js.map +1 -1
- package/dist/strand-peer-redial.js +2 -3
- package/dist/strand-peer-redial.js.map +1 -1
- package/dist/types.d.ts +286 -103
- package/dist/types.js.map +1 -1
- package/package.json +11 -2
- package/src/bootstrap-peer-store-file.ts +44 -44
- package/src/bootstrap-peer-store.ts +214 -214
- package/src/cadre-invite-protocol.ts +652 -1052
- package/src/cadre-join-request.ts +24 -3
- package/src/cadre-node.ts +1166 -541
- package/src/control-authorization.ts +47 -14
- package/src/control-cohort.ts +127 -128
- package/src/control-database.ts +940 -456
- package/src/control-protocol-guard.ts +7 -4
- package/src/control-schema-version.ts +251 -0
- package/src/control-schema.ts +265 -70
- package/src/control-write-retry.ts +569 -567
- package/src/delegate-admission.ts +37 -0
- package/src/ed25519-key.ts +174 -171
- package/src/edge-node/config.ts +277 -0
- package/src/edge-node/dissolve.ts +251 -0
- package/src/edge-node/edge-join.ts +319 -0
- package/src/edge-node/edge-node.ts +1045 -0
- package/src/edge-node/index.ts +59 -0
- package/src/edge-node/join-credential.ts +16 -0
- package/src/edge-node/lazy-raw-storage.ts +178 -0
- package/src/edge-node/node-local.ts +84 -0
- package/src/edge-node/options.ts +179 -0
- package/src/edge-node/owner-grant.ts +63 -0
- package/src/edge-node/platform.ts +151 -0
- package/src/edge-node/strand-move.ts +270 -0
- package/src/edge-node/strands.ts +72 -0
- package/src/index.ts +886 -789
- package/src/joined-strand-store.ts +4 -4
- package/src/key-store.ts +10 -4
- package/src/machine-removal.ts +26 -111
- package/src/member-redemption.ts +642 -0
- package/src/owner-anchor-sync.ts +19 -18
- package/src/owner-grant-protocol.ts +532 -0
- package/src/owner-key-export.ts +348 -0
- package/src/owner-key-flows.ts +109 -0
- package/src/owner-key-store.ts +85 -0
- package/src/owner-keys.ts +178 -0
- package/src/owner-signer.ts +94 -0
- package/src/peer-authorization.ts +558 -488
- package/src/provider/rent-node.ts +1 -1
- package/src/seed-bootstrap.ts +301 -312
- package/src/seed-trust-policy.ts +4 -4
- package/src/strand-addr-protocol.ts +547 -538
- package/src/strand-cohort.ts +4 -0
- package/src/strand-database.ts +3 -0
- package/src/strand-first-sync-gate.ts +4 -3
- package/src/strand-instance-manager.ts +1 -1
- package/src/strand-membership-writer.ts +61 -16
- package/src/strand-move.ts +45 -36
- package/src/strand-peer-redial.ts +2 -3
- package/src/types.ts +304 -103
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
* CHECK the `'reissue'`-tagged digest `ControlDatabase.reissueRevocations`
|
|
44
44
|
* signs — and `countRows` counts it.
|
|
45
45
|
*/
|
|
46
|
-
export declare const CONTROL_TABLES: readonly ["OwnerKey", "ValidationKey", "Strand", "StrandPartyKey", "JoinedStrand", "JoinRequest", "JoinSuccess", "JoinFailure", "CadrePeer", "DeviceToken", "FormationInvite", "FormationUsage", "CadreInvite", "CadreInviteUsage", "Revocation"];
|
|
46
|
+
export declare const CONTROL_TABLES: readonly ["OwnerKey", "ValidationKey", "Strand", "StrandPartyKey", "JoinedStrand", "JoinRequest", "JoinSuccess", "JoinFailure", "CadrePeer", "DeviceToken", "FormationInvite", "FormationUsage", "CadreInvite", "CadreInviteUsage", "OwnerGrant", "OwnerGrantUsage", "Revocation"];
|
|
47
47
|
/**
|
|
48
48
|
* Name of a CadreControl table. Doubles as the table half of a
|
|
49
49
|
* {@link ControlDomain} tag.
|
|
@@ -57,17 +57,17 @@ export type ControlTable = typeof CONTROL_TABLES[number];
|
|
|
57
57
|
* {@link ControlTable} rather than a fresh literal list, so a renamed table is a
|
|
58
58
|
* compile error here instead of a silently dead branch.
|
|
59
59
|
*
|
|
60
|
-
* `CadreInvite`
|
|
61
|
-
* withdrawal over a row that stays (`NotRevoked` refuses re-seating
|
|
62
|
-
* row; there is no `RevocationRecorded`, since nothing is ever removed), so
|
|
63
|
-
* revocable without being removable — `control-database.ts`'s `RemovableTable`
|
|
64
|
-
* excludes
|
|
60
|
+
* `CadreInvite` and `OwnerGrant` are the two members whose rows are never deleted: a
|
|
61
|
+
* tombstone there is a withdrawal over a row that stays (`NotRevoked` refuses re-seating
|
|
62
|
+
* the withdrawn row; there is no `RevocationRecorded`, since nothing is ever removed), so
|
|
63
|
+
* they are revocable without being removable — `control-database.ts`'s `RemovableTable`
|
|
64
|
+
* excludes them.
|
|
65
65
|
*
|
|
66
66
|
* Lives in this import-free module rather than beside its main consumer
|
|
67
67
|
* (`control-database.ts`) so the lightweight signers — `peer-authorization.ts`'s
|
|
68
68
|
* `revocationDigest` — can type against it without pulling in the runtime.
|
|
69
69
|
*/
|
|
70
|
-
export type RevocableTable = Extract<ControlTable, 'OwnerKey' | 'CadrePeer' | 'ValidationKey' | 'Strand' | 'StrandPartyKey' | 'JoinedStrand' | 'JoinRequest' | 'DeviceToken' | 'CadreInvite'>;
|
|
70
|
+
export type RevocableTable = Extract<ControlTable, 'OwnerKey' | 'CadrePeer' | 'ValidationKey' | 'Strand' | 'StrandPartyKey' | 'JoinedStrand' | 'JoinRequest' | 'DeviceToken' | 'CadreInvite' | 'OwnerGrant'>;
|
|
71
71
|
/**
|
|
72
72
|
* What a signature authorizes, scoped to one table rule — or, for
|
|
73
73
|
* `'Cadre.Enrollment'`, the offline peer vouch that `cadre enroll register`
|
|
@@ -99,10 +99,11 @@ export type BoundControlDomain = Exclude<ControlDomain, UnboundControlDomain>;
|
|
|
99
99
|
* owner key.
|
|
100
100
|
* - `'consent'` — a peer self-signs its OWN `FormationUsage` or
|
|
101
101
|
* `CadreInviteUsage` redemption (the joiner proving it agreed to join), with
|
|
102
|
-
* its own key
|
|
103
|
-
* the
|
|
104
|
-
*
|
|
105
|
-
*
|
|
102
|
+
* its own key, or the key an `OwnerGrantUsage` seats signs that it is held.
|
|
103
|
+
* Distinct from the approver's `'vouch'` over the same table so the two
|
|
104
|
+
* stored signatures are never interchangeable.
|
|
105
|
+
* - `'redeem'` — the holder of a `CadreInvite`'s or `OwnerGrant`'s private key
|
|
106
|
+
* proves possession on the usage row. Distinct from the `'consent'` over the
|
|
106
107
|
* same fields: the two signatures are by different keys and neither may stand
|
|
107
108
|
* in for the other.
|
|
108
109
|
* - `'reissue'` — an owner re-writes an existing `Revocation` tombstone,
|
|
@@ -121,7 +122,6 @@ export type ControlAction = 'add' | 'remove' | 'vouch' | 'publish' | 'consent' |
|
|
|
121
122
|
export interface CadreInviteSignedFields {
|
|
122
123
|
key: string;
|
|
123
124
|
peerId: string | null;
|
|
124
|
-
grantsOwner: boolean;
|
|
125
125
|
expiresAt: string | null;
|
|
126
126
|
totalUses: number | null;
|
|
127
127
|
stampId: string;
|
|
@@ -131,10 +131,32 @@ export interface CadreInviteSignedFields {
|
|
|
131
131
|
* (`control-database.ts`'s `cadreInviteAddMessage`, raw bytes) and the verifier
|
|
132
132
|
* (`peer-authorization.ts`'s `cadreInviteAddDigest`, base64url) so the two cannot
|
|
133
133
|
* drift. SQL mirror, in `CadreInvite.AuthorizedInsert`:
|
|
134
|
-
* `new.Key, coalesce(new.PeerId, ''), cast(new.
|
|
135
|
-
* coalesce(cast(new.
|
|
134
|
+
* `new.Key, coalesce(new.PeerId, ''), coalesce(cast(new.ExpiresAt as text), ''),
|
|
135
|
+
* coalesce(cast(new.TotalUses as text), ''), new.StampId`.
|
|
136
136
|
*/
|
|
137
137
|
export declare function cadreInviteRowFields(row: CadreInviteSignedFields): string[];
|
|
138
|
+
/**
|
|
139
|
+
* The `OwnerGrant` columns its `'add'` signature binds, in the schema's order and with
|
|
140
|
+
* the row's stored forms (`expiresAt` canonical, as {@link CadreInviteSignedFields}).
|
|
141
|
+
* `label` is the label the seated `OwnerKey` row must carry: the issuer's choice, bound
|
|
142
|
+
* here so the holder cannot seat the key under another name. Structurally satisfied by
|
|
143
|
+
* an `OwnerGrantRow` (`types.ts`), which adds the issuer pair the signature does not cover.
|
|
144
|
+
*/
|
|
145
|
+
export interface OwnerGrantSignedFields {
|
|
146
|
+
key: string;
|
|
147
|
+
label: string | null;
|
|
148
|
+
expiresAt: string | null;
|
|
149
|
+
totalUses: number | null;
|
|
150
|
+
stampId: string;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The row-field half of an `OwnerGrant` `'add'` digest, shared by the signer
|
|
154
|
+
* (`control-database.ts`'s `ownerGrantAddMessage`) and the verifier
|
|
155
|
+
* (`peer-authorization.ts`'s `ownerGrantAddDigest`), as {@link cadreInviteRowFields} is.
|
|
156
|
+
* SQL mirror, in `OwnerGrant.AuthorizedInsert`: `new.Key, coalesce(new.Label, ''),
|
|
157
|
+
* coalesce(cast(new.ExpiresAt as text), ''), coalesce(cast(new.TotalUses as text), ''), new.StampId`.
|
|
158
|
+
*/
|
|
159
|
+
export declare function ownerGrantRowFields(row: OwnerGrantSignedFields): string[];
|
|
138
160
|
/**
|
|
139
161
|
* The full ordered field vector a party-bound control-plane signature covers. Digest
|
|
140
162
|
* this with the crypto plugin's injective multi-field encoding (every field TEXT);
|
|
@@ -58,6 +58,8 @@ export const CONTROL_TABLES = [
|
|
|
58
58
|
'FormationUsage',
|
|
59
59
|
'CadreInvite',
|
|
60
60
|
'CadreInviteUsage',
|
|
61
|
+
'OwnerGrant',
|
|
62
|
+
'OwnerGrantUsage',
|
|
61
63
|
'Revocation',
|
|
62
64
|
];
|
|
63
65
|
/**
|
|
@@ -65,14 +67,29 @@ export const CONTROL_TABLES = [
|
|
|
65
67
|
* (`control-database.ts`'s `cadreInviteAddMessage`, raw bytes) and the verifier
|
|
66
68
|
* (`peer-authorization.ts`'s `cadreInviteAddDigest`, base64url) so the two cannot
|
|
67
69
|
* drift. SQL mirror, in `CadreInvite.AuthorizedInsert`:
|
|
68
|
-
* `new.Key, coalesce(new.PeerId, ''), cast(new.
|
|
69
|
-
* coalesce(cast(new.
|
|
70
|
+
* `new.Key, coalesce(new.PeerId, ''), coalesce(cast(new.ExpiresAt as text), ''),
|
|
71
|
+
* coalesce(cast(new.TotalUses as text), ''), new.StampId`.
|
|
70
72
|
*/
|
|
71
73
|
export function cadreInviteRowFields(row) {
|
|
72
74
|
return [
|
|
73
75
|
row.key,
|
|
74
76
|
row.peerId ?? '',
|
|
75
|
-
row.
|
|
77
|
+
row.expiresAt ?? '',
|
|
78
|
+
row.totalUses === null ? '' : String(row.totalUses),
|
|
79
|
+
row.stampId,
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The row-field half of an `OwnerGrant` `'add'` digest, shared by the signer
|
|
84
|
+
* (`control-database.ts`'s `ownerGrantAddMessage`) and the verifier
|
|
85
|
+
* (`peer-authorization.ts`'s `ownerGrantAddDigest`), as {@link cadreInviteRowFields} is.
|
|
86
|
+
* SQL mirror, in `OwnerGrant.AuthorizedInsert`: `new.Key, coalesce(new.Label, ''),
|
|
87
|
+
* coalesce(cast(new.ExpiresAt as text), ''), coalesce(cast(new.TotalUses as text), ''), new.StampId`.
|
|
88
|
+
*/
|
|
89
|
+
export function ownerGrantRowFields(row) {
|
|
90
|
+
return [
|
|
91
|
+
row.key,
|
|
92
|
+
row.label ?? '',
|
|
76
93
|
row.expiresAt ?? '',
|
|
77
94
|
row.totalUses === null ? '' : String(row.totalUses),
|
|
78
95
|
row.stampId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-authorization.js","sourceRoot":"","sources":["../src/control-authorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,UAAU;IACV,eAAe;IACf,QAAQ;IACR,gBAAgB;IAChB,cAAc;IACd,aAAa;IACb,aAAa;IACb,aAAa;IACb,WAAW;IACX,aAAa;IACb,iBAAiB;IACjB,gBAAgB;IAChB,aAAa;IACb,kBAAkB;IAClB,YAAY;CACJ,CAAC;AA2FX;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAA4B;IAC/D,OAAO;QACL,GAAG,CAAC,GAAG;QACP,GAAG,CAAC,MAAM,IAAI,EAAE;QAChB,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"control-authorization.js","sourceRoot":"","sources":["../src/control-authorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,UAAU;IACV,eAAe;IACf,QAAQ;IACR,gBAAgB;IAChB,cAAc;IACd,aAAa;IACb,aAAa;IACb,aAAa;IACb,WAAW;IACX,aAAa;IACb,iBAAiB;IACjB,gBAAgB;IAChB,aAAa;IACb,kBAAkB;IAClB,YAAY;IACZ,iBAAiB;IACjB,YAAY;CACJ,CAAC;AA2FX;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAA4B;IAC/D,OAAO;QACL,GAAG,CAAC,GAAG;QACP,GAAG,CAAC,MAAM,IAAI,EAAE;QAChB,GAAG,CAAC,SAAS,IAAI,EAAE;QACnB,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;QACnD,GAAG,CAAC,OAAO;KACZ,CAAC;AACJ,CAAC;AAiBD;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAA2B;IAC7D,OAAO;QACL,GAAG,CAAC,GAAG;QACP,GAAG,CAAC,KAAK,IAAI,EAAE;QACf,GAAG,CAAC,SAAS,IAAI,EAAE;QACnB,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;QACnD,GAAG,CAAC,OAAO;KACZ,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAA0B,EAC1B,MAAqB,EACrB,OAAe,EACf,SAAmB;IAEnB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAA4B,EAC5B,MAAqB,EACrB,SAAmB;IAEnB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;AACxC,CAAC"}
|
package/dist/control-cohort.d.ts
CHANGED
|
@@ -5,16 +5,16 @@
|
|
|
5
5
|
* connected (and thus replicating), without devolving into an N² mesh.
|
|
6
6
|
*
|
|
7
7
|
* FRET only needs a *connected* graph with the block clusters reachable, not a
|
|
8
|
-
* full mesh.
|
|
9
|
-
* that hold the control blocks, so the policy is **backbone-preferential
|
|
10
|
-
* bounded out-degree**:
|
|
8
|
+
* full mesh. Always-on (`storage` profile) machines are the stable, dialable
|
|
9
|
+
* backbone that hold the control blocks, so the policy is **backbone-preferential
|
|
10
|
+
* with a bounded out-degree**:
|
|
11
11
|
*
|
|
12
|
-
* - **Always dial every backbone (
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
12
|
+
* - **Always dial every backbone (always-on) member** — a party runs few of them,
|
|
13
|
+
* and they are the machines that stay reachable while phones sleep or roam.
|
|
14
|
+
* - **Fill the remainder** up to `targetDegree` with the other members (phones,
|
|
15
|
+
* and machines that have not yet published a profile), ordered
|
|
16
|
+
* deterministically (peerId sort) so every node makes the same stable choice
|
|
17
|
+
* across passes and load spreads predictably.
|
|
18
18
|
*
|
|
19
19
|
* For a small party (members ≤ degree) this degenerates to a full mesh, which is
|
|
20
20
|
* correct, cheap, and matches what the convergence tests do by hand; for a large
|
|
@@ -34,22 +34,22 @@ import type { CohortPeerRow } from './strand-cohort.js';
|
|
|
34
34
|
*/
|
|
35
35
|
export declare const DEFAULT_CONTROL_COHORT_RECONCILE_MS = 15000;
|
|
36
36
|
/**
|
|
37
|
-
* Default cap on the number of **non-
|
|
38
|
-
* proactively dials. Backbone (
|
|
37
|
+
* Default cap on the number of **non-backbone** members a single reconcile pass
|
|
38
|
+
* proactively dials. Backbone (always-on) members are always dialed and do NOT
|
|
39
39
|
* count against this cap.
|
|
40
40
|
*/
|
|
41
41
|
export declare const DEFAULT_CONTROL_COHORT_TARGET_DEGREE = 6;
|
|
42
42
|
/** Outcome of {@link selectControlCohortDials}: who to dial + what the cap dropped. */
|
|
43
43
|
export interface ControlCohortSelection {
|
|
44
44
|
/**
|
|
45
|
-
* Siblings to dial this pass, backbone first then the bounded non-
|
|
45
|
+
* Siblings to dial this pass, backbone first then the bounded non-backbone
|
|
46
46
|
* fill. Already self-excluded (the caller must pass self-excluded `siblings`).
|
|
47
47
|
* Still includes peers that may turn out to be already-connected — the caller
|
|
48
48
|
* diffs against live connections separately.
|
|
49
49
|
*/
|
|
50
50
|
dials: CohortPeerRow[];
|
|
51
|
-
/** Non-
|
|
52
|
-
|
|
51
|
+
/** Non-backbone members dropped by the `targetDegree` cap (0 when none). */
|
|
52
|
+
cappedNonBackbone: number;
|
|
53
53
|
}
|
|
54
54
|
/** What one {@link CadreNode.reconcileControlCohort} pass did. */
|
|
55
55
|
export interface ControlCohortReconcileResult {
|
|
@@ -68,15 +68,14 @@ export interface ControlCohortReconcileResult {
|
|
|
68
68
|
* Backbone-preferential, bounded-out-degree selection of control-cohort siblings
|
|
69
69
|
* to dial.
|
|
70
70
|
*
|
|
71
|
-
* A member is **backbone** iff
|
|
72
|
-
* (
|
|
73
|
-
*
|
|
74
|
-
*
|
|
71
|
+
* A member is **backbone** iff its `CadrePeer` row declares the `storage` profile
|
|
72
|
+
* (an always-on machine). All backbone members are selected; the rest fill up to
|
|
73
|
+
* `targetDegree` in deterministic peerId order. A member whose profile is still
|
|
74
|
+
* unknown (it has not self-published) is not backbone until it publishes one.
|
|
75
|
+
* A profile is a dial preference only: it is self-declared, and a machine
|
|
76
|
+
* misdeclaring one costs extra dials, never access.
|
|
75
77
|
*
|
|
76
78
|
* @param siblings - cadre members EXCLUDING self (the caller filters self out).
|
|
77
|
-
* @param
|
|
78
|
-
* before owner convergence, in which case no member classifies as backbone
|
|
79
|
-
* yet and the bounded fill still makes progress (preference sharpens later).
|
|
80
|
-
* @param targetDegree - cap on non-owner dials (negative is treated as 0).
|
|
79
|
+
* @param targetDegree - cap on non-backbone dials (negative is treated as 0).
|
|
81
80
|
*/
|
|
82
|
-
export declare function selectControlCohortDials(siblings: CohortPeerRow[],
|
|
81
|
+
export declare function selectControlCohortDials(siblings: CohortPeerRow[], targetDegree: number): ControlCohortSelection;
|
package/dist/control-cohort.js
CHANGED
|
@@ -5,22 +5,21 @@
|
|
|
5
5
|
* connected (and thus replicating), without devolving into an N² mesh.
|
|
6
6
|
*
|
|
7
7
|
* FRET only needs a *connected* graph with the block clusters reachable, not a
|
|
8
|
-
* full mesh.
|
|
9
|
-
* that hold the control blocks, so the policy is **backbone-preferential
|
|
10
|
-
* bounded out-degree**:
|
|
8
|
+
* full mesh. Always-on (`storage` profile) machines are the stable, dialable
|
|
9
|
+
* backbone that hold the control blocks, so the policy is **backbone-preferential
|
|
10
|
+
* with a bounded out-degree**:
|
|
11
11
|
*
|
|
12
|
-
* - **Always dial every backbone (
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
12
|
+
* - **Always dial every backbone (always-on) member** — a party runs few of them,
|
|
13
|
+
* and they are the machines that stay reachable while phones sleep or roam.
|
|
14
|
+
* - **Fill the remainder** up to `targetDegree` with the other members (phones,
|
|
15
|
+
* and machines that have not yet published a profile), ordered
|
|
16
|
+
* deterministically (peerId sort) so every node makes the same stable choice
|
|
17
|
+
* across passes and load spreads predictably.
|
|
18
18
|
*
|
|
19
19
|
* For a small party (members ≤ degree) this degenerates to a full mesh, which is
|
|
20
20
|
* correct, cheap, and matches what the convergence tests do by hand; for a large
|
|
21
21
|
* party it bounds out-degree to `backbone + targetDegree`.
|
|
22
22
|
*/
|
|
23
|
-
import { ed25519PublicKeyB64FromPeerId } from './ed25519-key.js';
|
|
24
23
|
/**
|
|
25
24
|
* Default recurring cadence for {@link CadreNode.reconcileControlCohort} (ms).
|
|
26
25
|
* In the same spirit as the 5s strand-watch poll but lighter, since a control
|
|
@@ -34,8 +33,8 @@ import { ed25519PublicKeyB64FromPeerId } from './ed25519-key.js';
|
|
|
34
33
|
*/
|
|
35
34
|
export const DEFAULT_CONTROL_COHORT_RECONCILE_MS = 15000;
|
|
36
35
|
/**
|
|
37
|
-
* Default cap on the number of **non-
|
|
38
|
-
* proactively dials. Backbone (
|
|
36
|
+
* Default cap on the number of **non-backbone** members a single reconcile pass
|
|
37
|
+
* proactively dials. Backbone (always-on) members are always dialed and do NOT
|
|
39
38
|
* count against this cap.
|
|
40
39
|
*/
|
|
41
40
|
export const DEFAULT_CONTROL_COHORT_TARGET_DEGREE = 6;
|
|
@@ -51,23 +50,24 @@ function byPeerId(a, b) {
|
|
|
51
50
|
* Backbone-preferential, bounded-out-degree selection of control-cohort siblings
|
|
52
51
|
* to dial.
|
|
53
52
|
*
|
|
54
|
-
* A member is **backbone** iff
|
|
55
|
-
* (
|
|
56
|
-
*
|
|
57
|
-
*
|
|
53
|
+
* A member is **backbone** iff its `CadrePeer` row declares the `storage` profile
|
|
54
|
+
* (an always-on machine). All backbone members are selected; the rest fill up to
|
|
55
|
+
* `targetDegree` in deterministic peerId order. A member whose profile is still
|
|
56
|
+
* unknown (it has not self-published) is not backbone until it publishes one.
|
|
57
|
+
* A profile is a dial preference only: it is self-declared, and a machine
|
|
58
|
+
* misdeclaring one costs extra dials, never access.
|
|
58
59
|
*
|
|
59
60
|
* @param siblings - cadre members EXCLUDING self (the caller filters self out).
|
|
60
|
-
* @param
|
|
61
|
-
* before owner convergence, in which case no member classifies as backbone
|
|
62
|
-
* yet and the bounded fill still makes progress (preference sharpens later).
|
|
63
|
-
* @param targetDegree - cap on non-owner dials (negative is treated as 0).
|
|
61
|
+
* @param targetDegree - cap on non-backbone dials (negative is treated as 0).
|
|
64
62
|
*/
|
|
65
|
-
export function selectControlCohortDials(siblings,
|
|
63
|
+
export function selectControlCohortDials(siblings, targetDegree) {
|
|
66
64
|
const backbone = [];
|
|
67
65
|
const rest = [];
|
|
66
|
+
// NOTE: the backbone is uncapped, so out-degree grows with the number of always-on
|
|
67
|
+
// machines (and with any sibling that declares `storage` without being one); if a party
|
|
68
|
+
// ever runs more than a handful, cap the backbone too.
|
|
68
69
|
for (const peer of siblings) {
|
|
69
|
-
|
|
70
|
-
if (pubKey !== null && ownerKeys.has(pubKey)) {
|
|
70
|
+
if (peer.profile === 'storage') {
|
|
71
71
|
backbone.push(peer);
|
|
72
72
|
}
|
|
73
73
|
else {
|
|
@@ -80,7 +80,7 @@ export function selectControlCohortDials(siblings, ownerKeys, targetDegree) {
|
|
|
80
80
|
const fill = rest.slice(0, cap);
|
|
81
81
|
return {
|
|
82
82
|
dials: [...backbone, ...fill],
|
|
83
|
-
|
|
83
|
+
cappedNonBackbone: rest.length - fill.length,
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
86
|
//# sourceMappingURL=control-cohort.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-cohort.js","sourceRoot":"","sources":["../src/control-cohort.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;
|
|
1
|
+
{"version":3,"file":"control-cohort.js","sourceRoot":"","sources":["../src/control-cohort.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,KAAM,CAAC;AAE1D;;;;GAIG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC,CAAC;AAkCtD,mFAAmF;AACnF,SAAS,QAAQ,CAAC,CAAgB,EAAE,CAAgB;IAClD,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAyB,EACzB,YAAoB;IAEpB,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,IAAI,GAAoB,EAAE,CAAC;IAEjC,mFAAmF;IACnF,wFAAwF;IACxF,uDAAuD;IACvD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC/B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEhC,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC;QAC7B,iBAAiB,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM;KAC7C,CAAC;AACJ,CAAC"}
|