@serfab/cadre-core 1.14.0 → 1.16.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 +64 -29
- package/dist/cadre-invite-protocol.js +207 -38
- package/dist/cadre-invite-protocol.js.map +1 -1
- 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 +375 -79
- package/dist/cadre-node.js +758 -186
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-database.d.ts +92 -12
- package/dist/control-database.js +323 -142
- package/dist/control-database.js.map +1 -1
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +19 -3
- package/dist/control-schema.js.map +1 -1
- package/dist/ed25519-key.d.ts +7 -9
- package/dist/ed25519-key.js +20 -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 +12 -5
- package/dist/index.js +31 -6
- 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 +9 -4
- package/dist/link-budget.js +9 -4
- 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 +6 -5
- package/dist/membership-connection-gater.js +6 -5
- package/dist/membership-connection-gater.js.map +1 -1
- package/dist/node-claim-payload.d.ts +55 -0
- package/dist/node-claim-payload.js +108 -4
- package/dist/node-claim-payload.js.map +1 -1
- 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/peer-dial.d.ts +124 -27
- package/dist/peer-dial.js +254 -30
- package/dist/peer-dial.js.map +1 -1
- package/dist/peer-join-backfill.js +6 -0
- package/dist/peer-join-backfill.js.map +1 -1
- package/dist/peer-record.d.ts +6 -45
- package/dist/peer-record.js +8 -50
- package/dist/peer-record.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/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 +22 -5
- package/dist/seed-bootstrap.js +48 -25
- package/dist/seed-bootstrap.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 +4 -1
- 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-wake-protocol.js +10 -7
- package/dist/strand-wake-protocol.js.map +1 -1
- package/dist/types.d.ts +212 -4
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -1
- package/package.json +18 -10
- package/src/cadre-invite-protocol.ts +1052 -864
- package/src/cadre-join-request.ts +167 -0
- package/src/cadre-node.ts +10003 -9381
- package/src/control-database.ts +4663 -4451
- package/src/control-schema.ts +19 -3
- package/src/ed25519-key.ts +20 -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 +71 -4
- 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 +9 -4
- package/src/machine-removal.ts +216 -0
- package/src/membership-connection-gater.ts +638 -637
- package/src/node-claim-payload.ts +138 -4
- package/src/node-default-transports.ts +38 -0
- package/src/node-transports.ts +49 -0
- package/src/peer-dial.ts +604 -336
- package/src/peer-join-backfill.ts +6 -0
- package/src/peer-record.ts +159 -202
- 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/relay-addrs.ts +9 -4
- package/src/relay-reservation.ts +1211 -1121
- package/src/seed-bootstrap.ts +1502 -1471
- 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-wake-protocol.ts +10 -7
- package/src/types.ts +220 -4
|
@@ -2,7 +2,7 @@ import { Database } from '@quereus/quereus';
|
|
|
2
2
|
import type { SqlParameters } from '@quereus/quereus';
|
|
3
3
|
import type { Libp2p } from '@libp2p/interface';
|
|
4
4
|
import type { IRepo } from '@optimystic/db-core';
|
|
5
|
-
import type { StrandRow, JoinRequestRow, JoinOutcome, PendingJoin, PeerAddressRecord, CadrePeerRow, OwnerKeyRow, RevocationRow, RevocationLedgerOpenResult, DeviceTokenRecord, DeviceTokenRow, CadreInviteRow, CadreInviteUsageRow, CadreInviteRedemptionResult, CadreInviteStatus, SeedPeer } from './types.js';
|
|
5
|
+
import type { StrandRow, JoinRequestRow, JoinOutcome, PendingJoin, NodeProfile, PeerAddressRecord, CadrePeerRow, OwnerKeyRow, RevocationRow, RevocationLedgerOpenResult, DeviceTokenRecord, DeviceTokenRow, CadreInviteRow, CadreInviteUsageRow, CadreInviteRedemptionResult, CadreInviteStatus, SeedPeer, MachineRemovalResult } from './types.js';
|
|
6
6
|
import type { ControlTable, RevocableTable, BoundControlDomain, ControlAction, CadreInviteSignedFields } from './control-authorization.js';
|
|
7
7
|
import type { ControlRetryAbandonment } from './control-retry.js';
|
|
8
8
|
export type { ControlTable, RevocableTable, ControlDomain, ControlAction } from './control-authorization.js';
|
|
@@ -100,6 +100,12 @@ export interface FormationUsageResult {
|
|
|
100
100
|
/** The single-use nonce written to `UsageStampId` (the row's primary key) — the caller's, or a freshly minted one. */
|
|
101
101
|
usageStampId: string;
|
|
102
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Parse a nullable stored `datetime` column into epoch ms, mapping both "absent"
|
|
105
|
+
* and "unparseable" to null — i.e. "no expiry". Shared by every `ExpiresAt`
|
|
106
|
+
* reader so the NaN guard cannot drift between them.
|
|
107
|
+
*/
|
|
108
|
+
export declare function parseNullableStoredDatetimeMs(value: string | number | null | undefined): number | null;
|
|
103
109
|
/**
|
|
104
110
|
* Build the canonical authorization message that owner signatures are bound to.
|
|
105
111
|
*
|
|
@@ -325,6 +331,18 @@ export declare function projectSeedPeers(rows: readonly CadrePeerRow[], ownerKey
|
|
|
325
331
|
*/
|
|
326
332
|
export declare const REAPABLE_TABLES: readonly ["CadrePeer", "DeviceToken", "ValidationKey", "JoinedStrand", "JoinRequest"];
|
|
327
333
|
export type ReapableTable = (typeof REAPABLE_TABLES)[number];
|
|
334
|
+
/** A `FormationInvite` row as {@link ControlDatabase.queryFormationInvite} reads it. */
|
|
335
|
+
export interface FormationInviteRow {
|
|
336
|
+
token: string;
|
|
337
|
+
sAppId: string;
|
|
338
|
+
/** Parsed epoch ms of the stored `datetime`; null when the invitation never expires. */
|
|
339
|
+
expiresAtMs: number | null;
|
|
340
|
+
/** Null is unlimited. */
|
|
341
|
+
totalUses: number | null;
|
|
342
|
+
validationUrl: string | null;
|
|
343
|
+
/** A bound invitation's host strand; null on the responder-provisions path. */
|
|
344
|
+
strandId: string | null;
|
|
345
|
+
}
|
|
328
346
|
/**
|
|
329
347
|
* Notified after a membership write (a `CadreControl.CadrePeer` or `OwnerKey` row, see
|
|
330
348
|
* {@link ControlDatabase.mutateCadrePeer}) has COMMITTED.
|
|
@@ -343,6 +361,8 @@ export type MembershipChangeListener = (reason: string) => Promise<void>;
|
|
|
343
361
|
* the writer that files the row supplies it.
|
|
344
362
|
*/
|
|
345
363
|
export type RevokedRowRef = Pick<RevocationRow, 'tableName' | 'rowKey' | 'stampId'>;
|
|
364
|
+
/** What {@link ControlDatabase.removeMachine} wrote: `CadreNode.removeMachine`'s result, less the re-vouches it made first. */
|
|
365
|
+
export type MachineRemovalWrites = Pick<MachineRemovalResult, 'removedPeer' | 'removedOwnerKey' | 'removedDeviceToken' | 'withdrawnInvitations'>;
|
|
346
366
|
/**
|
|
347
367
|
* Notified after a guarded-table delete — and the `CadreControl.Revocation`
|
|
348
368
|
* tombstone it writes in the same transaction — has COMMITTED.
|
|
@@ -972,6 +992,57 @@ export declare class ControlDatabase {
|
|
|
972
992
|
* @throws when `key` is `ownerKey`, or is the only live owner.
|
|
973
993
|
*/
|
|
974
994
|
deleteOwnerKey(key: string, ownerKey: string, signMessage: (message: Uint8Array) => string): Promise<boolean>;
|
|
995
|
+
/**
|
|
996
|
+
* Re-vouch a live `OwnerKey` row under this owner's signature: in ONE transaction, the
|
|
997
|
+
* current row's guarded delete plus tombstone ({@link deleteOwnerKey}'s body) and an insert
|
|
998
|
+
* of the same key under a fresh stamp, signed by `ownerKey` ({@link insertOwnerKeyVouched}'s
|
|
999
|
+
* body), as {@link rewritePendingJoin} re-seats a request. `OwnerKey` has `NoUpdate`, so
|
|
1000
|
+
* this is the only way to rebind a row's voucher; the anchor derivation lets the re-add
|
|
1001
|
+
* under a fresh stamp beat the older tombstone (`deriveOwnerAnchor`). For
|
|
1002
|
+
* {@link removeMachine}: the owners a machine being removed had added keep their anchor
|
|
1003
|
+
* place everywhere once their row stands on a remaining owner's signature.
|
|
1004
|
+
*
|
|
1005
|
+
* Through {@link mutateCadrePeer}, the membership hub. The stamp read runs inside the locked
|
|
1006
|
+
* body; a row whose stamp is already retired (held without its delete) is reported as absent
|
|
1007
|
+
* rather than tombstoned twice.
|
|
1008
|
+
*
|
|
1009
|
+
* @returns `true` when the row was re-vouched, `false` when `key` is not a live owner here.
|
|
1010
|
+
* @throws when `key` is `ownerKey` (an owner cannot sign its own row's removal).
|
|
1011
|
+
*/
|
|
1012
|
+
revouchOwnerKey(key: string, ownerKey: string, signMessage: (message: Uint8Array) => string): Promise<boolean>;
|
|
1013
|
+
/**
|
|
1014
|
+
* Remove one machine completely, in ONE transaction: its `CadrePeer` row, its `OwnerKey`
|
|
1015
|
+
* row when `target.ownerKey` names one, its `DeviceToken` row when it has one, each with
|
|
1016
|
+
* the `Revocation` tombstone retiring its stamp ({@link deleteGuardedRow}'s statement pair,
|
|
1017
|
+
* composed bare as {@link deleteStrandAndPartyKey} composes it), plus a withdrawal tombstone
|
|
1018
|
+
* for every `CadreInvite` in `target.inviteKeys` that is still live here
|
|
1019
|
+
* ({@link withdrawCadreInvite}'s body). One transaction so no reader sees the machine half
|
|
1020
|
+
* removed: a row gone but its push token resolvable, or its owner key gone but an invitation
|
|
1021
|
+
* it could redeem again still open.
|
|
1022
|
+
*
|
|
1023
|
+
* Through {@link mutateCadrePeer}, the membership hub. Every stamp is read inside the locked
|
|
1024
|
+
* body, and a row whose stamp is already retired (held without its delete) is skipped rather
|
|
1025
|
+
* than tombstoned twice. The by-name owner refusals of {@link deleteOwnerKey} apply to the
|
|
1026
|
+
* owner-key arm. Nothing to remove writes nothing and returns all false.
|
|
1027
|
+
*
|
|
1028
|
+
* The caller decides WHAT to remove, which owner key is the machine's and which invitations
|
|
1029
|
+
* it could use, from its plan (`CadreNode.planMachineRemoval`); this method only refuses to
|
|
1030
|
+
* write an inconsistent set.
|
|
1031
|
+
*
|
|
1032
|
+
* @throws when `target.ownerKey` is `ownerKey`, or is the only live owner here.
|
|
1033
|
+
*/
|
|
1034
|
+
removeMachine(target: {
|
|
1035
|
+
peerId: string;
|
|
1036
|
+
ownerKey: string | null;
|
|
1037
|
+
inviteKeys: readonly string[];
|
|
1038
|
+
}, ownerKey: string, signMessage: (message: Uint8Array) => string): Promise<MachineRemovalWrites>;
|
|
1039
|
+
/**
|
|
1040
|
+
* The guarded removals {@link removeMachine} runs, signed over each row's current stamp:
|
|
1041
|
+
* the `CadrePeer` row, the `OwnerKey` row when named, the `DeviceToken` row when present.
|
|
1042
|
+
* Inside the locked body (every read `retry: false`); one `Revocation` scan serves the
|
|
1043
|
+
* retired-stamp check for all three tables and the last-owner refusal.
|
|
1044
|
+
*/
|
|
1045
|
+
private signMachineRemovals;
|
|
975
1046
|
/**
|
|
976
1047
|
* Insert a strand into the control database using an owner signature.
|
|
977
1048
|
*
|
|
@@ -1214,6 +1285,7 @@ export declare class ControlDatabase {
|
|
|
1214
1285
|
multiaddr: string;
|
|
1215
1286
|
updatedAt: number;
|
|
1216
1287
|
sig: string | null;
|
|
1288
|
+
profile: NodeProfile | null;
|
|
1217
1289
|
}, ownerKey: string, signMessage: (message: Uint8Array) => string): Promise<boolean>;
|
|
1218
1290
|
/**
|
|
1219
1291
|
* Owner "re-touch" of an existing `CadrePeer` membership row: bump `UpdatedAt` and
|
|
@@ -1225,7 +1297,8 @@ export declare class ControlDatabase {
|
|
|
1225
1297
|
* local-only (its block's cluster ≤1 at insert) is pushed to the cohort once it grows, by
|
|
1226
1298
|
* re-issuing this monotonic bump. It is an UPDATE (not the original INSERT) because the row
|
|
1227
1299
|
* already exists locally; a re-INSERT would hit the `PeerId` PK. Only the freshness stamp
|
|
1228
|
-
* and voucher change — `PublicKey` / `Multiaddr` / `Sig` are left intact
|
|
1300
|
+
* and voucher change — `PublicKey` / `Multiaddr` / `Sig` / `Profile` are left intact (the
|
|
1301
|
+
* owner branch requires them kept: they are the machine's own claim) — so it is safe
|
|
1229
1302
|
* over a row whose peer has not self-published (`Sig` null); the caller must skip a row
|
|
1230
1303
|
* that already carries a self-`Sig` (that row is the owning peer's to refresh, and bumping
|
|
1231
1304
|
* `UpdatedAt` without re-signing would invalidate its self-signature).
|
|
@@ -1449,8 +1522,8 @@ export declare class ControlDatabase {
|
|
|
1449
1522
|
* a retired stamp, and which a revoked drone cannot produce at all. The trade is
|
|
1450
1523
|
* recurring failure noise every cycle against removing the one stale row nobody else
|
|
1451
1524
|
* reads from this node (every other node already filters it by tombstone). A revoked
|
|
1452
|
-
* node therefore keeps its own copy of its own row;
|
|
1453
|
-
*
|
|
1525
|
+
* node therefore keeps its own copy of its own row; learning that it was removed is a
|
|
1526
|
+
* separate behaviour (`CadreNode.removedFromCadre`, the `cadre:removed` event).
|
|
1454
1527
|
* `ValidationKey`, `JoinedStrand` and `JoinRequest` have no self notion and are not
|
|
1455
1528
|
* special-cased.
|
|
1456
1529
|
*
|
|
@@ -1941,14 +2014,13 @@ export declare class ControlDatabase {
|
|
|
1941
2014
|
* locked write body — same per-call opt-out, and for the same reason, as
|
|
1942
2015
|
* {@link queryStampId}'s. Every unlocked caller keeps the default retried path.
|
|
1943
2016
|
*/
|
|
1944
|
-
queryFormationInvite(token: string, retry?: boolean): Promise<
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
} | null>;
|
|
2017
|
+
queryFormationInvite(token: string, retry?: boolean): Promise<FormationInviteRow | null>;
|
|
2018
|
+
/**
|
|
2019
|
+
* Every `FormationInvite` row, expired and spent ones included, in the shape
|
|
2020
|
+
* {@link queryFormationInvite} returns one. Read by a strand move
|
|
2021
|
+
* (`exportStrandBundle`), which decides per row what is still redeemable.
|
|
2022
|
+
*/
|
|
2023
|
+
queryFormationInvites(): Promise<FormationInviteRow[]>;
|
|
1952
2024
|
/**
|
|
1953
2025
|
* Count `FormationUsage` rows recorded against a token (uses consumed so far).
|
|
1954
2026
|
*
|
|
@@ -2126,6 +2198,14 @@ export declare class ControlDatabase {
|
|
|
2126
2198
|
* node was alone is queued for re-issue on cohort growth ({@link CadreNode.noteGuardedDelete}).
|
|
2127
2199
|
*/
|
|
2128
2200
|
withdrawCadreInvite(key: string, ownerKey: string, signMessage: (message: Uint8Array) => string): Promise<boolean>;
|
|
2201
|
+
/**
|
|
2202
|
+
* The withdrawal tombstones for the `CadreInvite` rows among `keys` that are held here and
|
|
2203
|
+
* not yet withdrawn, signed and ready for {@link execTombstone}: the body
|
|
2204
|
+
* {@link withdrawCadreInvite} files one of and {@link removeMachine} files several of in one
|
|
2205
|
+
* transaction. Inside the locked body (every read `retry: false`); an absent or already
|
|
2206
|
+
* withdrawn key is logged and left out.
|
|
2207
|
+
*/
|
|
2208
|
+
private signCadreInviteWithdrawals;
|
|
2129
2209
|
/**
|
|
2130
2210
|
* Redeem a seated `CadreInvite` on the owner's behalf: admit `peerId` as a cadre member and,
|
|
2131
2211
|
* when the invitation grants ownership, as an owner — with NO owner signature. One
|