@serfab/cadre-core 1.16.0 → 1.18.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 +4 -3
- 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 +81 -142
- package/dist/cadre-invite-protocol.js +168 -458
- 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 +1089 -475
- package/dist/cadre-node.js +2170 -1037
- 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 +88 -32
- package/dist/control-cohort.js +91 -33
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +856 -318
- package/dist/control-database.js +1422 -701
- package/dist/control-database.js.map +1 -1
- package/dist/control-formation-recorder.d.ts +46 -43
- package/dist/control-formation-recorder.js +77 -78
- package/dist/control-formation-recorder.js.map +1 -1
- package/dist/control-protocol-guard.d.ts +11 -4
- package/dist/control-protocol-guard.js +20 -5
- package/dist/control-protocol-guard.js.map +1 -1
- package/dist/control-schema-version.d.ts +97 -0
- package/dist/control-schema-version.js +225 -0
- package/dist/control-schema-version.js.map +1 -0
- package/dist/control-schema.d.ts +45 -5
- package/dist/control-schema.js +262 -78
- package/dist/control-schema.js.map +1 -1
- package/dist/control-write-retry.d.ts +45 -10
- package/dist/control-write-retry.js +92 -22
- 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/enrolled-machine-store.d.ts +3 -3
- package/dist/enrolled-machine-store.js +3 -3
- package/dist/formation-token.d.ts +48 -0
- package/dist/formation-token.js +26 -0
- package/dist/formation-token.js.map +1 -0
- package/dist/index.d.ts +27 -17
- package/dist/index.js +39 -17
- package/dist/index.js.map +1 -1
- package/dist/joined-strand-store.d.ts +29 -12
- package/dist/joined-strand-store.js +66 -27
- 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/link-budget.d.ts +9 -7
- package/dist/link-budget.js +9 -7
- package/dist/link-budget.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 +256 -0
- package/dist/member-redemption.js +490 -0
- package/dist/member-redemption.js.map +1 -0
- package/dist/membership-view.d.ts +91 -0
- package/dist/membership-view.js +110 -0
- package/dist/membership-view.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 +251 -0
- package/dist/owner-grant-protocol.js +344 -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-addr-book.d.ts +10 -1
- package/dist/peer-addr-book.js +4 -3
- package/dist/peer-addr-book.js.map +1 -1
- 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/peer-join-backfill.d.ts +89 -20
- package/dist/peer-join-backfill.js +265 -108
- package/dist/peer-join-backfill.js.map +1 -1
- package/dist/pending-join-runner.d.ts +48 -18
- package/dist/pending-join-runner.js +74 -56
- package/dist/pending-join-runner.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 +162 -133
- package/dist/seed-bootstrap.js +300 -283
- 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 +24 -2
- package/dist/strand-database.js +29 -6
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +176 -88
- package/dist/strand-first-sync-gate.js +288 -121
- package/dist/strand-first-sync-gate.js.map +1 -1
- package/dist/strand-formation-deadlines.d.ts +9 -9
- package/dist/strand-formation-deadlines.js +9 -9
- package/dist/strand-formation-manager.d.ts +23 -17
- package/dist/strand-formation-manager.js +46 -44
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +5 -8
- package/dist/strand-formation-protocol.js +101 -16
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +27 -18
- package/dist/strand-instance-manager.js +119 -50
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-membership-reconciler.d.ts +16 -13
- package/dist/strand-membership-reconciler.js +30 -22
- package/dist/strand-membership-reconciler.js.map +1 -1
- package/dist/strand-membership-writer.d.ts +45 -22
- package/dist/strand-membership-writer.js +226 -131
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-move.d.ts +6 -5
- package/dist/strand-move.js +36 -32
- 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/strand-revocation-enforcer.d.ts +134 -60
- package/dist/strand-revocation-enforcer.js +144 -71
- package/dist/strand-revocation-enforcer.js.map +1 -1
- package/dist/strand-solicitation.d.ts +50 -39
- package/dist/strand-solicitation.js +10 -3
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/strand-watcher.d.ts +80 -13
- package/dist/strand-watcher.js +152 -48
- package/dist/strand-watcher.js.map +1 -1
- package/dist/table-change-watch.d.ts +63 -0
- package/dist/table-change-watch.js +209 -0
- package/dist/table-change-watch.js.map +1 -0
- package/dist/timeout-scheduler.d.ts +4 -3
- package/dist/timeout-scheduler.js +4 -3
- package/dist/timeout-scheduler.js.map +1 -1
- package/dist/types.d.ts +374 -150
- package/dist/types.js +4 -4
- package/dist/types.js.map +1 -1
- package/package.json +17 -8
- package/src/bootstrap-peer-store-file.ts +44 -44
- package/src/bootstrap-peer-store.ts +214 -214
- package/src/cadre-invite-protocol.ts +740 -1052
- package/src/cadre-join-request.ts +24 -3
- package/src/cadre-node.ts +2402 -1079
- package/src/control-authorization.ts +47 -14
- package/src/control-cohort.ts +204 -128
- package/src/control-database.ts +1749 -820
- package/src/control-formation-recorder.ts +359 -353
- package/src/control-protocol-guard.ts +23 -6
- package/src/control-schema-version.ts +301 -0
- package/src/control-schema.ts +273 -78
- package/src/control-write-retry.ts +641 -567
- package/src/delegate-admission.ts +351 -314
- 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/enrolled-machine-store.ts +3 -3
- package/src/formation-token.ts +63 -0
- package/src/index.ts +899 -789
- package/src/joined-strand-store.ts +73 -28
- package/src/key-store.ts +10 -4
- package/src/link-budget.ts +9 -7
- package/src/machine-removal.ts +26 -111
- package/src/member-redemption.ts +649 -0
- package/src/membership-view.ts +144 -0
- package/src/owner-anchor-sync.ts +19 -18
- package/src/owner-grant-protocol.ts +547 -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-addr-book.ts +4 -3
- package/src/peer-authorization.ts +558 -488
- package/src/peer-join-backfill.ts +971 -761
- package/src/pending-join-runner.ts +76 -53
- package/src/provider/rent-node.ts +1 -1
- package/src/seed-bootstrap.ts +343 -349
- 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 +352 -319
- package/src/strand-first-sync-gate.ts +334 -133
- package/src/strand-formation-deadlines.ts +227 -227
- package/src/strand-formation-manager.ts +731 -725
- package/src/strand-formation-protocol.ts +122 -24
- package/src/strand-instance-manager.ts +2092 -2026
- package/src/strand-membership-reconciler.ts +33 -25
- package/src/strand-membership-writer.ts +2093 -1974
- package/src/strand-move.ts +50 -38
- package/src/strand-peer-redial.ts +2 -3
- package/src/strand-revocation-enforcer.ts +740 -654
- package/src/strand-solicitation.ts +61 -34
- package/src/strand-watcher.ts +175 -56
- package/src/table-change-watch.ts +285 -0
- package/src/timeout-scheduler.ts +29 -28
- package/src/types.ts +391 -152
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CoordinatorPartialCommitError, SyncRetryExhaustedError, TornActionError } from '@optimystic/db-core';
|
|
2
|
-
import { PartialCommitError } from '@optimystic/quereus-plugin-optimystic';
|
|
2
|
+
import { ConcurrentModificationError, PartialCommitError } from '@optimystic/quereus-plugin-optimystic';
|
|
3
3
|
import { causeChain, chainMessages, retryControlOperation } from './control-retry.js';
|
|
4
4
|
/**
|
|
5
5
|
* Bounded retry for TRANSIENT control-write failures — the classifier and loop behind
|
|
@@ -30,12 +30,13 @@ import { causeChain, chainMessages, retryControlOperation } from './control-retr
|
|
|
30
30
|
* before any matcher runs. The one half-landed write that IS re-presented is a torn write the
|
|
31
31
|
* library marks final — not saved and unable to land ({@link isFinalTornWrite}).
|
|
32
32
|
*
|
|
33
|
-
*
|
|
33
|
+
* THREE policies ship from here, and the split is deliberate: the default
|
|
34
34
|
* ({@link isRetriableControlWriteFailure}, {@link CONTROL_WRITE_ATTEMPTS}) sits under every
|
|
35
|
-
* control write
|
|
36
|
-
* `ControlDatabase.
|
|
37
|
-
*
|
|
38
|
-
*
|
|
35
|
+
* control write; {@link SCHEMA_INIT_RETRY_POLICY} is opted into by
|
|
36
|
+
* `ControlDatabase.applyControlSchema` alone; {@link LOST_UPDATE_RETRY_POLICY} is opted into by
|
|
37
|
+
* the `CadrePeer` writers whose bodies re-read the row and decide again. Each widened one absorbs
|
|
38
|
+
* one extra failure class whose re-run safety holds for its opted-in bodies and NOT for writes in
|
|
39
|
+
* general; anything added to the default list must be safe for all ~19 callers.
|
|
39
40
|
*
|
|
40
41
|
* Lives outside `control-database.ts` so a spec can drive the classifier against real engine
|
|
41
42
|
* errors without importing the whole database class. The loop itself lives in
|
|
@@ -324,6 +325,33 @@ function isFinalTornWrite(link) {
|
|
|
324
325
|
function isUnansweredSuperMajorityShortfall(message) {
|
|
325
326
|
return SUPER_MAJORITY_SHORTFALL_UNANSWERED.test(message);
|
|
326
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* A LOST UPDATE: the optimystic bridge refusing a commit because another writer changed or
|
|
330
|
+
* removed a row this statement read (`TransactionBridge.mapCommitRefusal` over a
|
|
331
|
+
* `TreeEntryChangedError`, `quereus-plugin-optimystic/src/optimystic-adapter/txn-bridge.ts`).
|
|
332
|
+
* Claimed by TYPE for {@link LOST_UPDATE_RETRY_POLICY} only.
|
|
333
|
+
*
|
|
334
|
+
* Why it is a proven non-commit: the refusal is raised inside the action's atomic handler, so
|
|
335
|
+
* none of that action's entries land. A refusal after a sibling tree or collection of the same
|
|
336
|
+
* transaction already synced is not delivered bare — the per-tree sweep wraps it in
|
|
337
|
+
* `PartialCommitError`, the coordinator path in `CoordinatorPartialCommitError` — and
|
|
338
|
+
* {@link reportsPossiblyStoredWrite} vetoes both by type before this predicate runs. A bare chain
|
|
339
|
+
* carrying this class therefore means nothing of the write is durable.
|
|
340
|
+
*
|
|
341
|
+
* Why it is not in the default list: the rejection is of the write's READ SET, not of its
|
|
342
|
+
* signature, so re-presenting the same statement is only right when the body re-reads the row and
|
|
343
|
+
* decides again over what it finds. That is a property of each opted-in body (see the policy's
|
|
344
|
+
* `NOTE:`), not of control writes in general.
|
|
345
|
+
*
|
|
346
|
+
* Not matched by text: `ConcurrentModificationError` is exported from both the plugin's root and
|
|
347
|
+
* `/plugin` entries over one shared chunk, as `PartialCommitError` is, so the one `instanceof`
|
|
348
|
+
* covers both (the `NOTE:` on {@link reportsPossiblyStoredWrite} applies to it too). A second
|
|
349
|
+
* loaded copy of the plugin would fail the `instanceof` and the lost update would then simply not
|
|
350
|
+
* be retried — the safe side.
|
|
351
|
+
*/
|
|
352
|
+
function isLostUpdate(link) {
|
|
353
|
+
return link instanceof ConcurrentModificationError;
|
|
354
|
+
}
|
|
327
355
|
/**
|
|
328
356
|
* Optimystic refusing to let a node elect ITSELF coordinator because its last connection dropped
|
|
329
357
|
* less than the guard's grace period ago (`Libp2pKeyPeerNetwork.shouldAllowSelfCoordination` →
|
|
@@ -382,14 +410,16 @@ const RETRIABLE_CONTROL_WRITE_MATCHERS = [
|
|
|
382
410
|
* failed apply is taken back whole — Quereus unwinds every step it ran and verifies the catalog
|
|
383
411
|
* against a pre-apply fingerprint — so a re-run emits exactly the DDL the live catalog is missing.
|
|
384
412
|
* The full argument, including the plugin-side dependency that unwind carries, is at the
|
|
385
|
-
* `
|
|
413
|
+
* `applyControlSchema` call site in `control-database.ts`.
|
|
386
414
|
*
|
|
387
415
|
* RETRIED DELIBERATELY, not by oversight: the failures Quereus cannot take back. When the unwind
|
|
388
416
|
* does not complete — an undo statement threw, the post-unwind catalog did not match the pre-apply
|
|
389
417
|
* fingerprint, that catalog could not be re-collected to check, or a step the differ marks
|
|
390
418
|
* irreversible because it discards data (dropping a table or a column, narrowing a column's type —
|
|
391
|
-
*
|
|
392
|
-
*
|
|
419
|
+
* of which only dropping a column reaches a `CadreControl` apply, as the catalog-only migration
|
|
420
|
+
* step `refuseIncompatibleControlStore` in `control-schema-version.ts` lets through; it discards
|
|
421
|
+
* nothing there, since rows keep the field) poisoned the journal before it
|
|
422
|
+
* ran, leaving nothing unwound — Quereus keeps the failing step's own message, APPENDS the reason the
|
|
393
423
|
* schema could not be restored, and carries the original as `cause`. So a transient cause
|
|
394
424
|
* underneath still matches here, and neither veto ({@link reportsPossiblyStoredWrite},
|
|
395
425
|
* {@link reportsIndeterminateCommit}) looks for that reason text. Retrying over a partially migrated
|
|
@@ -432,7 +462,7 @@ export function isRetriableControlWriteFailure(error) {
|
|
|
432
462
|
}
|
|
433
463
|
/**
|
|
434
464
|
* {@link isRetriableControlWriteFailure} widened by exactly one class — the self-coordination
|
|
435
|
-
* grace refusal ({@link RETRIABLE_SCHEMA_INIT_MATCHERS}) — for `ControlDatabase.
|
|
465
|
+
* grace refusal ({@link RETRIABLE_SCHEMA_INIT_MATCHERS}) — for `ControlDatabase.applyControlSchema`.
|
|
436
466
|
*
|
|
437
467
|
* Opt-in per call site, via {@link SCHEMA_INIT_RETRY_POLICY}. Every other control write keeps the
|
|
438
468
|
* default classifier untouched.
|
|
@@ -441,14 +471,26 @@ export function isRetriableSchemaInitFailure(error) {
|
|
|
441
471
|
return matchesRetriableFailure(error, RETRIABLE_SCHEMA_INIT_MATCHERS);
|
|
442
472
|
}
|
|
443
473
|
/**
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
* still declined because a sibling collection landed.
|
|
474
|
+
* {@link isRetriableControlWriteFailure} widened by exactly one class — a lost update
|
|
475
|
+
* ({@link isLostUpdate}), claimed by type — for the `CadrePeer` writers that re-read the row inside
|
|
476
|
+
* their locked body. Opt-in per call site, via {@link LOST_UPDATE_RETRY_POLICY}; both vetoes still
|
|
477
|
+
* run first, so a lost update carried inside a partial commit, a spent sync budget or a non-final
|
|
478
|
+
* torn write stays declined.
|
|
450
479
|
*/
|
|
451
|
-
function
|
|
480
|
+
export function isRetriableLostUpdateFailure(error) {
|
|
481
|
+
return matchesRetriableFailure(error, RETRIABLE_CONTROL_WRITE_MATCHERS, isLostUpdate);
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Shared body of the three classifiers: walk the `cause` chain, let
|
|
485
|
+
* {@link reportsPossiblyStoredWrite} and then {@link reportsIndeterminateCommit} veto it, then claim
|
|
486
|
+
* a final torn write ({@link isFinalTornWrite}) or any link `claimsLink` names, then ask `matchers`.
|
|
487
|
+
* The vetoes run BEFORE any claim for every policy — a chain reporting a possibly-stored write or a
|
|
488
|
+
* commit-phase batch is never retried, however transient some other level looks, and a final torn
|
|
489
|
+
* write or a lost update carried by a partial commit is still declined because a sibling collection
|
|
490
|
+
* landed. `claimsLink` is the one typed claim a policy may add; it sits here beside the torn-write
|
|
491
|
+
* claim so the vetoes stay in one place above both.
|
|
492
|
+
*/
|
|
493
|
+
function matchesRetriableFailure(error, matchers, claimsLink) {
|
|
452
494
|
if (!(error instanceof Error)) {
|
|
453
495
|
return false;
|
|
454
496
|
}
|
|
@@ -460,13 +502,13 @@ function matchesRetriableFailure(error, matchers) {
|
|
|
460
502
|
if (reportsIndeterminateCommit(messages)) {
|
|
461
503
|
return false;
|
|
462
504
|
}
|
|
463
|
-
if (links.some(isFinalTornWrite)) {
|
|
505
|
+
if (links.some(link => isFinalTornWrite(link) || claimsLink?.(link) === true)) {
|
|
464
506
|
return true;
|
|
465
507
|
}
|
|
466
508
|
return messages.some(message => matchers.some(matches => matches(message)));
|
|
467
509
|
}
|
|
468
510
|
/**
|
|
469
|
-
* The
|
|
511
|
+
* The schema-init policy: `ControlDatabase.applyControlSchema`'s distributed DDL, which
|
|
470
512
|
* additionally absorbs optimystic's self-coordination grace refusal and gets more attempts over a
|
|
471
513
|
* longer backoff to do it (see {@link SCHEMA_INIT_ATTEMPTS} and
|
|
472
514
|
* {@link SCHEMA_INIT_RETRY_DELAYS_MS}). Still bounded by the shared
|
|
@@ -474,16 +516,44 @@ function matchesRetriableFailure(error, matchers) {
|
|
|
474
516
|
*
|
|
475
517
|
* NOTE: exactly one call site opts in today, and the re-run safety this policy assumes is that
|
|
476
518
|
* site's, not a general property — `apply schema` is a diff, and a failed apply is unwound whole
|
|
477
|
-
* and verified against the pre-apply catalog (full argument at the `
|
|
478
|
-
* `control-database.ts`). A second opt-in must re-derive that argument for its own write body
|
|
519
|
+
* and verified against the pre-apply catalog (full argument at the `applyControlSchema` call site
|
|
520
|
+
* in `control-database.ts`). A second opt-in must re-derive that argument for its own write body
|
|
479
521
|
* first; if this policy ever grows a third consumer, rename it for what the callers share rather
|
|
480
|
-
* than widening it by default.
|
|
522
|
+
* than widening it by default. {@link LOST_UPDATE_RETRY_POLICY} is a separate policy for a
|
|
523
|
+
* separate class, not a second consumer of this one.
|
|
481
524
|
*/
|
|
482
525
|
export const SCHEMA_INIT_RETRY_POLICY = {
|
|
483
526
|
attempts: SCHEMA_INIT_ATTEMPTS,
|
|
484
527
|
delaysMs: SCHEMA_INIT_RETRY_DELAYS_MS,
|
|
485
528
|
isRetriable: isRetriableSchemaInitFailure,
|
|
486
529
|
};
|
|
530
|
+
/**
|
|
531
|
+
* The lost-update policy: the default classifier plus a lost update claimed by type
|
|
532
|
+
* ({@link isRetriableLostUpdateFailure}), over the default attempts, backoff and budget. A re-run
|
|
533
|
+
* here is a RE-DECISION, not a re-presentation: the body reads the row again under the lock and
|
|
534
|
+
* signs over what it finds, so the write that lost to a rival is replaced by one made over the
|
|
535
|
+
* rival's result. The budget bounds it as it bounds every write — a losing attempt whose read
|
|
536
|
+
* phase waited out one per-peer read deadline (~7.5 s measured in the degraded-cohort scenario's
|
|
537
|
+
* trio boot) gets exactly one retry, which is the ceiling to expect; one that waited out two
|
|
538
|
+
* (14.7 s, measured once in 18 of that scenario's boots, on the member that cannot reach one
|
|
539
|
+
* sibling) gets none and is abandoned on the budget, and the lost publish is then the reconcile
|
|
540
|
+
* pass's or the heartbeat's to redo, as every abandoned self-publish is.
|
|
541
|
+
*
|
|
542
|
+
* NOTE: the re-run safety this policy assumes is each opted-in body's, not a general property. A
|
|
543
|
+
* body may opt in only when its read of the row, its decision and its signature ALL run inside
|
|
544
|
+
* the locked body, so that the re-run presents a write made over the row as it now stands rather
|
|
545
|
+
* than the first attempt's signed record (which the rival may have stamped past, or which may
|
|
546
|
+
* overwrite what the rival wrote). Three `CadrePeer` writers opt in, through
|
|
547
|
+
* `ControlDatabase.mutateCadrePeer`'s policy parameter or `lockedWithRetry` directly:
|
|
548
|
+
* `updateSelfPeerRecord` (re-reads and re-signs the node's own record), `reauthorizeCadrePeer`
|
|
549
|
+
* (re-reads the stamp and decides again whether the row is still the owner's to re-touch) and
|
|
550
|
+
* the two removals `deleteCadrePeer` / `removeMachine` (stamp read and signature already inside
|
|
551
|
+
* the body, and a self-publish never changes the stamp the `'remove'` digest binds). A new opt-in
|
|
552
|
+
* must re-derive that argument for its own body first.
|
|
553
|
+
*/
|
|
554
|
+
export const LOST_UPDATE_RETRY_POLICY = {
|
|
555
|
+
isRetriable: isRetriableLostUpdateFailure,
|
|
556
|
+
};
|
|
487
557
|
/**
|
|
488
558
|
* Run `attempt` up to {@link CONTROL_WRITE_ATTEMPTS} times (or `options.attempts`), retrying only
|
|
489
559
|
* failures the policy's classifier — {@link isRetriableControlWriteFailure} by default —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-write-retry.js","sourceRoot":"","sources":["../src/control-write-retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC9G,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"control-write-retry.js","sourceRoot":"","sources":["../src/control-write-retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
* {@link dueRelayAnnounces} and {@link prunePeerStrandKeys} are that
|
|
39
39
|
* decision, pure and testable, kept here beside the TTL they are derived from.
|
|
40
40
|
*/
|
|
41
|
+
import type { StrandAddrOutcome } from './strand-addr-protocol.js';
|
|
41
42
|
/**
|
|
42
43
|
* How long one announced delegate grant stays valid without a re-announce.
|
|
43
44
|
* Announcers refresh at half this (`CadreNode`'s reconcile pass), so a live
|
|
@@ -121,6 +122,18 @@ export declare function extractCircuitRelayTargets(addrs: string[]): CircuitRela
|
|
|
121
122
|
* {@link peerStrandKey} on the peer announced TO.
|
|
122
123
|
*/
|
|
123
124
|
export declare function dueRelayAnnounces(announceAt: ReadonlyMap<string, number>, relays: readonly CircuitRelayTarget[], strandId: string, now: number, ttlMs?: number): CircuitRelayTarget[];
|
|
125
|
+
/**
|
|
126
|
+
* Fold one announce pass's outcomes into `refusing`, the relay peerIds remembered
|
|
127
|
+
* as refusing the strand-addr protocol. A relay whose negotiation refused it
|
|
128
|
+
* (`unsupported`) is added; one that replied with any status is removed, because
|
|
129
|
+
* it serves the protocol now. A relay that did not reply (`unreachable`) is left
|
|
130
|
+
* as it was: being down says nothing about what it serves. Only `relayPeerIds`
|
|
131
|
+
* are read, so a sibling asked in the same pass is never recorded. Mutates in
|
|
132
|
+
* place.
|
|
133
|
+
*/
|
|
134
|
+
export declare function recordRelayRefusals(refusing: Set<string>, relayPeerIds: readonly string[], outcomes: ReadonlyMap<string, StrandAddrOutcome>): void;
|
|
135
|
+
/** Of `relays`, the ones not remembered in `refusing` (see {@link recordRelayRefusals}). */
|
|
136
|
+
export declare function relaysNotRefusing(relays: readonly CircuitRelayTarget[], refusing: ReadonlySet<string>): CircuitRelayTarget[];
|
|
124
137
|
/**
|
|
125
138
|
* Drop the entries of a {@link peerStrandKey}-keyed map whose strand is no longer
|
|
126
139
|
* running, and — when `livePeerIds` is given — whose peer is not among them. A
|
|
@@ -183,6 +183,33 @@ export function extractCircuitRelayTargets(addrs) {
|
|
|
183
183
|
export function dueRelayAnnounces(announceAt, relays, strandId, now, ttlMs = DELEGATE_GRANT_TTL_MS) {
|
|
184
184
|
return relays.filter((relay) => now - (announceAt.get(peerStrandKey(relay.relayPeerId, strandId)) ?? 0) >= ttlMs / 2);
|
|
185
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Fold one announce pass's outcomes into `refusing`, the relay peerIds remembered
|
|
188
|
+
* as refusing the strand-addr protocol. A relay whose negotiation refused it
|
|
189
|
+
* (`unsupported`) is added; one that replied with any status is removed, because
|
|
190
|
+
* it serves the protocol now. A relay that did not reply (`unreachable`) is left
|
|
191
|
+
* as it was: being down says nothing about what it serves. Only `relayPeerIds`
|
|
192
|
+
* are read, so a sibling asked in the same pass is never recorded. Mutates in
|
|
193
|
+
* place.
|
|
194
|
+
*/
|
|
195
|
+
export function recordRelayRefusals(refusing, relayPeerIds, outcomes) {
|
|
196
|
+
for (const relayPeerId of relayPeerIds) {
|
|
197
|
+
switch (outcomes.get(relayPeerId)) {
|
|
198
|
+
case 'unsupported':
|
|
199
|
+
refusing.add(relayPeerId);
|
|
200
|
+
break;
|
|
201
|
+
case 'answered':
|
|
202
|
+
case 'empty':
|
|
203
|
+
case 'unavailable':
|
|
204
|
+
refusing.delete(relayPeerId);
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/** Of `relays`, the ones not remembered in `refusing` (see {@link recordRelayRefusals}). */
|
|
210
|
+
export function relaysNotRefusing(relays, refusing) {
|
|
211
|
+
return relays.filter((relay) => !refusing.has(relay.relayPeerId));
|
|
212
|
+
}
|
|
186
213
|
/**
|
|
187
214
|
* Drop the entries of a {@link peerStrandKey}-keyed map whose strand is no longer
|
|
188
215
|
* running, and — when `livePeerIds` is given — whose peer is not among them. A
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delegate-admission.js","sourceRoot":"","sources":["../src/delegate-admission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"delegate-admission.js","sourceRoot":"","sources":["../src/delegate-admission.ts"],"names":[],"mappings":"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"}
|
package/dist/ed25519-key.d.ts
CHANGED
|
@@ -40,6 +40,16 @@ export declare function ed25519KeyPairFromLibp2p(privateKey: PrivateKey): Ed2551
|
|
|
40
40
|
* @returns The base64url-encoded Ed25519 public key.
|
|
41
41
|
*/
|
|
42
42
|
export declare function ed25519PublicKeyFromPrivate(privateKeyB64: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Reject a value that isn't a base64url-encoded 32-byte Ed25519 seed, the private-key form
|
|
45
|
+
* {@link ed25519PublicKeyFromPrivate} and the crypto plugin's `sign` take. Unlike
|
|
46
|
+
* {@link requireEd25519PublicKeyB64}, no message names the value: it is a private key.
|
|
47
|
+
*
|
|
48
|
+
* @param value - Candidate base64url-encoded Ed25519 seed; surrounding whitespace is ignored.
|
|
49
|
+
* @param label - Human-readable name of the field, used in error messages.
|
|
50
|
+
* @returns The seed re-encoded as canonical base64url, so two spellings of one key compare equal.
|
|
51
|
+
*/
|
|
52
|
+
export declare function requireEd25519PrivateKeyB64(value: string, label: string): string;
|
|
43
53
|
/**
|
|
44
54
|
* Derive the base64url ed25519 public key embedded in an Ed25519 libp2p PeerId.
|
|
45
55
|
*
|
|
@@ -55,13 +65,6 @@ export declare function ed25519PublicKeyFromPrivate(privateKeyB64: string): stri
|
|
|
55
65
|
* without importing the seed-bootstrap runtime.
|
|
56
66
|
*/
|
|
57
67
|
export declare function ed25519PublicKeyB64FromPeerId(peerId: string): string | null;
|
|
58
|
-
/**
|
|
59
|
-
* The inverse of {@link ed25519PublicKeyB64FromPeerId}: the libp2p peer id whose identity
|
|
60
|
-
* is this ed25519 public key (base64url), or null when the value does not decode to a
|
|
61
|
-
* 32-byte key. How an `OwnerKey` row is matched to the machine it names
|
|
62
|
-
* (`machine-removal.ts`), since a machine's owner key is the key behind its peer id.
|
|
63
|
-
*/
|
|
64
|
-
export declare function peerIdFromEd25519PublicKeyB64(publicKeyB64: string): string | null;
|
|
65
68
|
/**
|
|
66
69
|
* Reject a value that isn't shaped like a base64url-encoded 32-byte Ed25519 public key
|
|
67
70
|
* before it reaches the control database, where a malformed key would otherwise sit
|
package/dist/ed25519-key.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays';
|
|
2
2
|
import { getPublicKey } from '@optimystic/quereus-plugin-crypto';
|
|
3
|
-
import {
|
|
4
|
-
import { publicKeyFromRaw } from '@libp2p/crypto/keys';
|
|
3
|
+
import { peerIdFromString } from '@libp2p/peer-id';
|
|
5
4
|
/**
|
|
6
5
|
* Bridge a libp2p Ed25519 private key into the base64url keypair used by the
|
|
7
6
|
* control- and strand-database signing constraints.
|
|
@@ -50,6 +49,28 @@ export function ed25519KeyPairFromLibp2p(privateKey) {
|
|
|
50
49
|
export function ed25519PublicKeyFromPrivate(privateKeyB64) {
|
|
51
50
|
return getPublicKey(privateKeyB64, 'ed25519', 'base64url', 'base64url');
|
|
52
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Reject a value that isn't a base64url-encoded 32-byte Ed25519 seed, the private-key form
|
|
54
|
+
* {@link ed25519PublicKeyFromPrivate} and the crypto plugin's `sign` take. Unlike
|
|
55
|
+
* {@link requireEd25519PublicKeyB64}, no message names the value: it is a private key.
|
|
56
|
+
*
|
|
57
|
+
* @param value - Candidate base64url-encoded Ed25519 seed; surrounding whitespace is ignored.
|
|
58
|
+
* @param label - Human-readable name of the field, used in error messages.
|
|
59
|
+
* @returns The seed re-encoded as canonical base64url, so two spellings of one key compare equal.
|
|
60
|
+
*/
|
|
61
|
+
export function requireEd25519PrivateKeyB64(value, label) {
|
|
62
|
+
let decoded;
|
|
63
|
+
try {
|
|
64
|
+
decoded = uint8ArrayFromString(value.trim(), 'base64url');
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw new Error(`The ${label} must be a base64url-encoded Ed25519 private key (it does not decode as base64url)`, { cause: error });
|
|
68
|
+
}
|
|
69
|
+
if (decoded.length !== 32) {
|
|
70
|
+
throw new Error(`The ${label} must be a base64url-encoded 32-byte Ed25519 private key (it decoded to ${decoded.length} bytes)`);
|
|
71
|
+
}
|
|
72
|
+
return uint8ArrayToString(decoded, 'base64url');
|
|
73
|
+
}
|
|
53
74
|
/**
|
|
54
75
|
* Derive the base64url ed25519 public key embedded in an Ed25519 libp2p PeerId.
|
|
55
76
|
*
|
|
@@ -76,24 +97,6 @@ export function ed25519PublicKeyB64FromPeerId(peerId) {
|
|
|
76
97
|
return null;
|
|
77
98
|
}
|
|
78
99
|
}
|
|
79
|
-
/**
|
|
80
|
-
* The inverse of {@link ed25519PublicKeyB64FromPeerId}: the libp2p peer id whose identity
|
|
81
|
-
* is this ed25519 public key (base64url), or null when the value does not decode to a
|
|
82
|
-
* 32-byte key. How an `OwnerKey` row is matched to the machine it names
|
|
83
|
-
* (`machine-removal.ts`), since a machine's owner key is the key behind its peer id.
|
|
84
|
-
*/
|
|
85
|
-
export function peerIdFromEd25519PublicKeyB64(publicKeyB64) {
|
|
86
|
-
try {
|
|
87
|
-
const raw = uint8ArrayFromString(publicKeyB64, 'base64url');
|
|
88
|
-
if (raw.length !== 32) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
return peerIdFromPublicKey(publicKeyFromRaw(raw)).toString();
|
|
92
|
-
}
|
|
93
|
-
catch {
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
100
|
/** Longest rejected key value echoed back in an error — a real key is 43 base64url chars. */
|
|
98
101
|
const REJECTED_VALUE_ECHO_LIMIT = 64;
|
|
99
102
|
/**
|
package/dist/ed25519-key.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ed25519-key.js","sourceRoot":"","sources":["../src/ed25519-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ed25519-key.js","sourceRoot":"","sources":["../src/ed25519-key.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The edge node's `CadreNodeConfig` and how a start settles its owner key. Nothing here needs a
|
|
3
|
+
* node started, so a test can build the node shape an edge device runs.
|
|
4
|
+
*/
|
|
5
|
+
import { type KeyStore } from '../key-store.js';
|
|
6
|
+
import type { CadreNode } from '../cadre-node.js';
|
|
7
|
+
import type { CadreNodeConfig } from '../types.js';
|
|
8
|
+
import type { BootstrapPeerStore } from '../bootstrap-peer-store.js';
|
|
9
|
+
import type { EnrolledMachineStore } from '../enrolled-machine-store.js';
|
|
10
|
+
import type { StrandNetworkStateStore } from '../strand-network-state.js';
|
|
11
|
+
import type { TrustedOwnerStore } from '../trusted-owner-store.js';
|
|
12
|
+
import type { IRawStorage, Libp2pTransports, NoiseCryptoInterface } from '@optimystic/db-p2p';
|
|
13
|
+
import type { EdgeNodeOptions } from './options.js';
|
|
14
|
+
/** What {@link buildEdgeNodeConfig} takes: one start's options plus what the platform built. */
|
|
15
|
+
export interface EdgeNodeConfigInputs extends EdgeNodeOptions {
|
|
16
|
+
/** `undefined` keeps libp2p-noise's own crypto. */
|
|
17
|
+
noiseCrypto?: NoiseCryptoInterface;
|
|
18
|
+
/**
|
|
19
|
+
* Holds the node identity, which the node loads on start, generating it on first run, and the
|
|
20
|
+
* owner key in its own slot (`DEFAULT_OWNER_KEY_ID`), which only {@link runOwnerGenesis} creates.
|
|
21
|
+
*/
|
|
22
|
+
keyStore: KeyStore;
|
|
23
|
+
/**
|
|
24
|
+
* Raw block storage per cadre-core storage scope: `controlStorageScope(partyId)` for the
|
|
25
|
+
* control network, the strand id for each strand. The key is already safe as a database-name
|
|
26
|
+
* segment — use it verbatim, do not parse it.
|
|
27
|
+
*/
|
|
28
|
+
storageProvider: (scope: string) => IRawStorage;
|
|
29
|
+
/** libp2p transport factories: what the node dials with, and what listens on `listenAddrs`. */
|
|
30
|
+
transports: Libp2pTransports;
|
|
31
|
+
/**
|
|
32
|
+
* Listen addresses besides the bare `/p2p-circuit` entry cadre-core adds for a named relay.
|
|
33
|
+
* Default `[]`: an edge device accepts no inbound connection. See `EdgeNodePlatform.listenAddrs`.
|
|
34
|
+
*/
|
|
35
|
+
listenAddrs?: string[];
|
|
36
|
+
/** See `EdgeNodePlatform.allowPrivateDial`. */
|
|
37
|
+
allowPrivateDial: boolean;
|
|
38
|
+
trustedOwnerStore: TrustedOwnerStore;
|
|
39
|
+
bootstrapPeerStore: BootstrapPeerStore;
|
|
40
|
+
enrolledMachineStore: EnrolledMachineStore;
|
|
41
|
+
strandNetworkStateStore: StrandNetworkStateStore;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The edge node's config: transaction profile (Ring Zulu only, intermittent connectivity), no
|
|
45
|
+
* listen address unless the platform names one, reachability through the configured relays (if
|
|
46
|
+
* any) but never a hard requirement for one, every strand the control network lists, and no
|
|
47
|
+
* automatic hibernation (the app's lifecycle runner hibernates on background). Schema signing is
|
|
48
|
+
* left at cadre-core's fail-closed default; an app with unsigned schemas relaxes it in
|
|
49
|
+
* `EdgeNodePlatform.configure`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildEdgeNodeConfig(inputs: EdgeNodeConfigInputs): CadreNodeConfig;
|
|
52
|
+
/**
|
|
53
|
+
* How the start settled this node's owner key: `EdgeNodeStatus.owner`. `'enrolled'`: a key is
|
|
54
|
+
* an owner and wired for signing. `'member'`: the party lists no key this app holds (a party it
|
|
55
|
+
* joined, or one it founded whose owner slot was lost). `'failed'` and `'timed-out'`: see
|
|
56
|
+
* {@link runOwnerGenesis}.
|
|
57
|
+
*/
|
|
58
|
+
export type OwnerGenesisResult = 'enrolled' | 'member' | 'failed' | 'timed-out';
|
|
59
|
+
/**
|
|
60
|
+
* Default bound on {@link runOwnerGenesis} and {@link wireJoinedOwnerKey}: what a start can wait
|
|
61
|
+
* for its owner step, which runs control reads and one control write, before it goes on without
|
|
62
|
+
* it. Not derived from the link, since a start that waited out a stalled write (about 84 s, see
|
|
63
|
+
* `docs/cadre-consistency.md`) would be a start the user gave up on.
|
|
64
|
+
*/
|
|
65
|
+
export declare const DEFAULT_OWNER_GENESIS_TIMEOUT_MS = 60000;
|
|
66
|
+
/** Default `EdgeNodeOptions.ownerKeyLabel`: the founding owner key's name on its `OwnerKey` row. */
|
|
67
|
+
export declare const DEFAULT_OWNER_KEY_LABEL = "phone";
|
|
68
|
+
/**
|
|
69
|
+
* Refuses an `ownerKeyLabel` the founding `OwnerKey` row would refuse, so a start naming one
|
|
70
|
+
* fails outright: fail-soft genesis would only log it, on that start and every later one.
|
|
71
|
+
*/
|
|
72
|
+
export declare function requireOwnerKeyLabel(label: string | undefined): void;
|
|
73
|
+
/** What {@link runOwnerGenesis} takes. */
|
|
74
|
+
export interface OwnerGenesisOptions {
|
|
75
|
+
/** The key store whose owner slot holds this app's owner key: the one the identity is in. */
|
|
76
|
+
keyStore: KeyStore;
|
|
77
|
+
/** The founding row's label; default {@link DEFAULT_OWNER_KEY_LABEL}. */
|
|
78
|
+
label?: string;
|
|
79
|
+
/** Default {@link DEFAULT_OWNER_GENESIS_TIMEOUT_MS}. */
|
|
80
|
+
timeoutMs?: number;
|
|
81
|
+
}
|
|
82
|
+
/** What {@link wireJoinedOwnerKey} takes. */
|
|
83
|
+
export interface JoinedOwnerKeyOptions {
|
|
84
|
+
/** The key store whose owner slot holds this app's owner key, if it holds one. */
|
|
85
|
+
keyStore: KeyStore;
|
|
86
|
+
/** Default {@link DEFAULT_OWNER_GENESIS_TIMEOUT_MS}. */
|
|
87
|
+
timeoutMs?: number;
|
|
88
|
+
/** An owner grant has just seated the slot's key: keep asking until the row arrives. */
|
|
89
|
+
granted?: boolean;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The owner step of a party this app founded. On a party with no `OwnerKey` row yet, the owner
|
|
93
|
+
* slot's key (created there now unless the slot already holds one) becomes the founding owner
|
|
94
|
+
* under `label` and is wired for signing, which also lets the node author its own `CadrePeer` row.
|
|
95
|
+
* On a party that has owners, the slot's key is wired only when it is a live owner, and no key is
|
|
96
|
+
* created: a new one could not be seated without another owner's signature. A node must be an
|
|
97
|
+
* enrolled owner to publish strands, and `CadreNode.requestJoin` works only on one. A joined
|
|
98
|
+
* party's start runs {@link wireJoinedOwnerKey} instead.
|
|
99
|
+
*
|
|
100
|
+
* Fail-soft and bounded: a failure or a genesis that has not settled within `timeoutMs` is logged
|
|
101
|
+
* and returned, and the start stands — the app can still join discovered strands and sync. A
|
|
102
|
+
* genesis that times out keeps running; its later failure is logged.
|
|
103
|
+
*
|
|
104
|
+
* NOTE: the bound is here, in cadre-core, so every edge node gets it; a Node host runs genesis
|
|
105
|
+
* through the CLI's own flow instead. Since v1.10 a control write against an unresponsive member
|
|
106
|
+
* can hold the write lock for about 84 s, so an unbounded wait here would be a real stall. A bound
|
|
107
|
+
* on that write itself, in `ControlDatabase`, would make this one redundant; drop `timeoutMs` then.
|
|
108
|
+
*/
|
|
109
|
+
export declare function runOwnerGenesis(node: CadreNode, options: OwnerGenesisOptions): Promise<OwnerGenesisResult>;
|
|
110
|
+
/**
|
|
111
|
+
* The owner step of a party this app joined: wire a key only when the party lists it as a live
|
|
112
|
+
* owner, never insert an `OwnerKey` row, so a joined app can neither seat itself as a founder nor
|
|
113
|
+
* anchor a key that is no owner's. Only the owner slot's key is tried: the key an owner grant
|
|
114
|
+
* seated, one imported here, or one an owner of the party added. The identity key is never
|
|
115
|
+
* tried, since a machine's network identity is never an owner key. Fail-soft and bounded as
|
|
116
|
+
* {@link runOwnerGenesis} is.
|
|
117
|
+
*
|
|
118
|
+
* `granted`: an owner grant has just made this app an owner, so a key not listed yet means the
|
|
119
|
+
* row has not reached this node, not that it is no owner. It is asked again every 2 s until it
|
|
120
|
+
* is wired or the bound passes; a start that timed out wires it on the next start.
|
|
121
|
+
*/
|
|
122
|
+
export declare function wireJoinedOwnerKey(node: CadreNode, options: JoinedOwnerKeyOptions): Promise<OwnerGenesisResult>;
|