@kubun/plugin-p2p 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/context/delegation.js +130 -1
- package/lib/context/group.js +1319 -1
- package/lib/context/hub.js +150 -1
- package/lib/context/join.js +80 -1
- package/lib/context/sync.js +19 -1
- package/lib/context/types.d.ts +12 -3
- package/lib/context/types.js +28 -1
- package/lib/groups/admin-roster.d.ts +130 -0
- package/lib/groups/admin-roster.js +184 -0
- package/lib/groups/broadcast-codec.js +6 -1
- package/lib/groups/broadcast.d.ts +122 -38
- package/lib/groups/broadcast.js +627 -1
- package/lib/groups/circle-projection.d.ts +122 -0
- package/lib/groups/circle-projection.js +288 -0
- package/lib/groups/circle-reducers.d.ts +178 -0
- package/lib/groups/circle-reducers.js +198 -0
- package/lib/groups/events.d.ts +7 -2
- package/lib/groups/events.js +10 -1
- package/lib/groups/group-anchor.d.ts +63 -0
- package/lib/groups/group-anchor.js +107 -0
- package/lib/groups/group-crypto.d.ts +19 -0
- package/lib/groups/group-crypto.js +85 -0
- package/lib/groups/group-handle-registry.d.ts +69 -2
- package/lib/groups/group-handle-registry.js +243 -1
- package/lib/groups/group-handlers.d.ts +29 -0
- package/lib/groups/group-handlers.js +92 -0
- package/lib/groups/group-health-monitor.d.ts +56 -0
- package/lib/groups/group-health-monitor.js +139 -0
- package/lib/groups/group-mls.d.ts +35 -0
- package/lib/groups/group-mls.js +164 -0
- package/lib/groups/group-peer-manager.d.ts +108 -0
- package/lib/groups/group-peer-manager.js +344 -0
- package/lib/groups/group-protocols.d.ts +297 -0
- package/lib/groups/group-protocols.js +174 -0
- package/lib/groups/invite-payload.d.ts +1 -1
- package/lib/groups/invite-payload.js +26 -1
- package/lib/groups/join-utils.d.ts +1 -0
- package/lib/groups/join-utils.js +104 -1
- package/lib/groups/ledger-affected-events.d.ts +15 -0
- package/lib/groups/ledger-affected-events.js +96 -0
- package/lib/groups/ledger-entry.d.ts +37 -0
- package/lib/groups/ledger-entry.js +56 -0
- package/lib/groups/ledger-fold.d.ts +56 -0
- package/lib/groups/ledger-fold.js +53 -0
- package/lib/groups/manager.d.ts +29 -71
- package/lib/groups/manager.js +281 -1
- package/lib/groups/mls-codec.d.ts +1 -1
- package/lib/groups/mls-codec.js +18 -1
- package/lib/groups/mls-encryptor.d.ts +2 -2
- package/lib/groups/mls-encryptor.js +30 -1
- package/lib/groups/mls-group-handle.d.ts +1 -1
- package/lib/groups/mls-group-handle.js +10 -1
- package/lib/groups/mls-json.js +17 -1
- package/lib/groups/mls-receive-errors.d.ts +29 -0
- package/lib/groups/mls-receive-errors.js +42 -0
- package/lib/groups/mls-state.d.ts +1 -1
- package/lib/groups/mls-state.js +56 -1
- package/lib/groups/store-received-grant.d.ts +4 -1
- package/lib/groups/store-received-grant.js +116 -1
- package/lib/groups/store-received-revocation.d.ts +3 -3
- package/lib/groups/store-received-revocation.js +82 -1
- package/lib/hub/ack-backoff.d.ts +22 -0
- package/lib/hub/ack-backoff.js +88 -0
- package/lib/hub/did-observing-transport.d.ts +13 -2
- package/lib/hub/did-observing-transport.js +126 -1
- package/lib/hub/errors.d.ts +4 -8
- package/lib/hub/errors.js +33 -1
- package/lib/hub/http-client.d.ts +28 -3
- package/lib/hub/http-client.js +32 -1
- package/lib/hub/hub-like.d.ts +24 -0
- package/lib/hub/hub-like.js +535 -0
- package/lib/hub/manager.d.ts +5 -4
- package/lib/hub/manager.js +198 -1
- package/lib/hub/wiring.d.ts +28 -41
- package/lib/hub/wiring.js +132 -1
- package/lib/index.d.ts +29 -13
- package/lib/index.js +392 -1
- package/lib/protocol.d.ts +8 -1
- package/lib/protocol.js +251 -1
- package/lib/schema.d.ts +2 -1
- package/lib/schema.js +471 -2
- package/lib/sync/authorize.d.ts +25 -0
- package/lib/sync/authorize.js +73 -0
- package/lib/sync/broadcast-queue.js +183 -1
- package/lib/sync/broadcast-sender.js +179 -1
- package/lib/sync/catalog-scope.js +68 -1
- package/lib/sync/errors.d.ts +12 -0
- package/lib/sync/errors.js +19 -0
- package/lib/sync/forwarder.js +277 -1
- package/lib/sync/handlers.d.ts +3 -22
- package/lib/sync/handlers.js +160 -1
- package/lib/sync/hub-tunnel-sync-listener.d.ts +9 -3
- package/lib/sync/hub-tunnel-sync-listener.js +172 -1
- package/lib/sync/hub-tunnel-sync-provider.d.ts +14 -14
- package/lib/sync/hub-tunnel-sync-provider.js +64 -1
- package/lib/sync/merkle-apply.d.ts +5 -0
- package/lib/sync/merkle-apply.js +194 -1
- package/lib/sync/merkle-channel.d.ts +19 -0
- package/lib/sync/merkle-channel.js +182 -1
- package/lib/sync/merkle-tree.js +120 -1
- package/lib/sync/peer-registry.d.ts +8 -1
- package/lib/sync/peer-registry.js +107 -1
- package/lib/sync/receive-access-gate.js +24 -1
- package/lib/sync/scope-resolver.js +41 -1
- package/lib/sync/sync-client.d.ts +5 -3
- package/lib/sync/sync-client.js +192 -1
- package/lib/sync/sync-manager.d.ts +2 -2
- package/lib/sync/sync-manager.js +272 -1
- package/lib/types.d.ts +41 -0
- package/lib/types.js +2 -1
- package/lib/util/mutex.js +10 -1
- package/lib/utils.d.ts +5 -0
- package/lib/utils.js +21 -0
- package/package.json +48 -41
- package/lib/groups/broadcast-service.d.ts +0 -189
- package/lib/groups/broadcast-service.js +0 -1
- package/lib/groups/wire-frame.d.ts +0 -32
- package/lib/groups/wire-frame.js +0 -1
- package/lib/hub/connection-pool.d.ts +0 -43
- package/lib/hub/connection-pool.js +0 -1
- package/lib/hub/forward-remote-broadcast.d.ts +0 -15
- package/lib/hub/forward-remote-broadcast.js +0 -1
- package/lib/hub/group-channel.d.ts +0 -67
- package/lib/hub/group-channel.js +0 -1
- package/lib/hub/hub-connection.d.ts +0 -96
- package/lib/hub/hub-connection.js +0 -1
- package/lib/hub/receive-handler.d.ts +0 -33
- package/lib/hub/receive-handler.js +0 -1
- package/lib/hub/relay-manager.d.ts +0 -127
- package/lib/hub/relay-manager.js +0 -1
- package/lib/hub/send-handler.d.ts +0 -40
- package/lib/hub/send-handler.js +0 -1
- package/lib/hub/tunnel-inbox.d.ts +0 -20
- package/lib/hub/tunnel-inbox.js +0 -1
- package/lib/hub/wait-for-gate.d.ts +0 -14
- package/lib/hub/wait-for-gate.js +0 -1
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { DefaultAccessLevel, GraphInternals } from '@kubun/engine';
|
|
2
|
+
import { HLC } from '@kubun/hlc';
|
|
2
3
|
import type { Logger } from '@kubun/logger';
|
|
3
|
-
import type { CatalogRecord
|
|
4
|
-
import type {
|
|
4
|
+
import type { CatalogRecord } from '@kubun/protocol';
|
|
5
|
+
import type { DelegationStoreAPI } from '@kubun/store-delegation';
|
|
6
|
+
import type { GraphStoreAPI } from '@kubun/store-graph';
|
|
5
7
|
import type { Circle, CircleMember, Group, P2PStoreAPI } from '@kubun/store-p2p';
|
|
6
8
|
import { type ForwardingConfig } from '../sync/forwarder.js';
|
|
7
9
|
import type { StoreUnreadableMode } from '../types.js';
|
|
8
10
|
import type { P2PEventEmitter } from './events.js';
|
|
11
|
+
import type { GroupAnchor } from './group-anchor.js';
|
|
9
12
|
export type MutationApplyEntry = {
|
|
10
13
|
mutationJWT: string;
|
|
11
14
|
docID: string;
|
|
@@ -13,33 +16,18 @@ export type MutationApplyEntry = {
|
|
|
13
16
|
version: string;
|
|
14
17
|
modelID: string;
|
|
15
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* Optional signed token over a control operation. Its issuer (`iss`) is the
|
|
21
|
+
* authenticated author; receivers verify it and authorize that author as a
|
|
22
|
+
* group admin, dropping the operation when the token is absent or invalid. The
|
|
23
|
+
* signed payload is the whole message minus this field, so the signature covers
|
|
24
|
+
* every operation field, not just the author.
|
|
25
|
+
*/
|
|
26
|
+
type ControlAuth = string;
|
|
16
27
|
export type GroupBroadcastMessage = {
|
|
17
|
-
type: 'circle:create';
|
|
18
|
-
circle: CircleRecord;
|
|
19
|
-
} | {
|
|
20
|
-
type: 'circle:update';
|
|
21
|
-
circleID: string;
|
|
22
|
-
update: {
|
|
23
|
-
name?: string;
|
|
24
|
-
description?: string;
|
|
25
|
-
catalogIDs?: Array<string>;
|
|
26
|
-
hlc: string;
|
|
27
|
-
};
|
|
28
|
-
} | {
|
|
29
|
-
type: 'circle:delete';
|
|
30
|
-
circleID: string;
|
|
31
|
-
hlc: string;
|
|
32
|
-
} | {
|
|
33
|
-
type: 'member:add';
|
|
34
|
-
member: CircleMemberRecord;
|
|
35
|
-
} | {
|
|
36
|
-
type: 'member:remove';
|
|
37
|
-
circleID: string;
|
|
38
|
-
memberDID: string;
|
|
39
|
-
hlc: string;
|
|
40
|
-
} | {
|
|
41
28
|
type: 'catalog:create';
|
|
42
29
|
catalog: CatalogRecord;
|
|
30
|
+
auth?: ControlAuth;
|
|
43
31
|
} | {
|
|
44
32
|
type: 'catalog:update';
|
|
45
33
|
catalogID: string;
|
|
@@ -49,10 +37,12 @@ export type GroupBroadcastMessage = {
|
|
|
49
37
|
filterCriteria?: CatalogRecord['filterCriteria'];
|
|
50
38
|
hlc: string;
|
|
51
39
|
};
|
|
40
|
+
auth?: ControlAuth;
|
|
52
41
|
} | {
|
|
53
42
|
type: 'catalog:delete';
|
|
54
43
|
catalogID: string;
|
|
55
44
|
hlc: string;
|
|
45
|
+
auth?: ControlAuth;
|
|
56
46
|
} | {
|
|
57
47
|
/**
|
|
58
48
|
* Distributes a minted `document/write` capability token to group
|
|
@@ -85,13 +75,9 @@ export type GroupBroadcastMessage = {
|
|
|
85
75
|
/** HLC stamped by the revoker; mirrors the revoker-side stored row. */
|
|
86
76
|
hlc: string;
|
|
87
77
|
} | {
|
|
88
|
-
type: '
|
|
78
|
+
type: 'ledger:entry';
|
|
89
79
|
groupID: string;
|
|
90
|
-
|
|
91
|
-
name?: string;
|
|
92
|
-
description?: string;
|
|
93
|
-
hlc: string;
|
|
94
|
-
};
|
|
80
|
+
token: string;
|
|
95
81
|
} | {
|
|
96
82
|
/**
|
|
97
83
|
* A member announces a voluntary leave. MLS forbids self-removal, so this
|
|
@@ -109,20 +95,62 @@ export type GroupBroadcastMessage = {
|
|
|
109
95
|
entries: Array<MutationApplyEntry>;
|
|
110
96
|
/** DID of the peer that authored this broadcast — used for loopback drop. */
|
|
111
97
|
senderPeerDID: string;
|
|
98
|
+
} | {
|
|
99
|
+
/**
|
|
100
|
+
* A rejoining peer asks current members for the group's full control
|
|
101
|
+
* ledger so it can backfill entries it missed while absent. `requestID`
|
|
102
|
+
* correlates the eventual batched reply.
|
|
103
|
+
*/
|
|
104
|
+
type: 'ledger-catchup:request';
|
|
105
|
+
requestID: string;
|
|
106
|
+
} | {
|
|
107
|
+
/**
|
|
108
|
+
* A member's reply to a `ledger-catchup:request`: the group's control
|
|
109
|
+
* ledger as an array of signed entry tokens. The responder is UNTRUSTED —
|
|
110
|
+
* each token self-authenticates, so the requester re-verifies every one
|
|
111
|
+
* independently and a forged or unsigned token is dropped without
|
|
112
|
+
* poisoning the rest. Idempotent + order-independent on the token digest.
|
|
113
|
+
*/
|
|
114
|
+
type: 'ledger-catchup:reply';
|
|
115
|
+
requestID: string;
|
|
116
|
+
entries: Array<string>;
|
|
112
117
|
};
|
|
113
|
-
|
|
114
|
-
|
|
118
|
+
/** Narrow {@link GroupBroadcastMessage} to the variant(s) carrying the given `type`. */
|
|
119
|
+
export type BroadcastOf<TType extends GroupBroadcastMessage['type']> = Extract<GroupBroadcastMessage, {
|
|
120
|
+
type: TType;
|
|
121
|
+
}>;
|
|
122
|
+
/**
|
|
123
|
+
* The local-event descriptor for an applied `ledger:entry`. The ingest arm
|
|
124
|
+
* captures it after reprojecting, while the store still holds the post-state,
|
|
125
|
+
* so {@link forwardRemoteBroadcast} can emit the matching local event for a
|
|
126
|
+
* remote-driven change without re-reading or re-verifying. Each variant carries
|
|
127
|
+
* the projected row plus the create-vs-change / add-vs-remove discriminators the
|
|
128
|
+
* ingest derived by comparing the pre-state it read before reprojecting.
|
|
129
|
+
*/
|
|
130
|
+
export type LedgerAffected = {
|
|
131
|
+
entry: 'circle.def';
|
|
132
|
+
row: Circle;
|
|
133
|
+
/** True when an active circle row existed before this entry (changed, not created). */
|
|
134
|
+
preExisted: boolean;
|
|
135
|
+
/** True when the entry's catalog set differs from the pre-state's (catalogs changed). */
|
|
136
|
+
catalogsChanged: boolean;
|
|
137
|
+
} | {
|
|
138
|
+
entry: 'circle.def.removed';
|
|
115
139
|
row: Circle;
|
|
116
140
|
} | {
|
|
117
|
-
|
|
141
|
+
entry: 'circle.member';
|
|
118
142
|
row: CircleMember;
|
|
119
143
|
} | {
|
|
120
|
-
|
|
121
|
-
row:
|
|
144
|
+
entry: 'circle.member.removed';
|
|
145
|
+
row: CircleMember;
|
|
122
146
|
} | {
|
|
123
|
-
|
|
147
|
+
entry: 'group.settings';
|
|
124
148
|
row: Group;
|
|
125
149
|
};
|
|
150
|
+
export type AffectedRow = {
|
|
151
|
+
kind: 'ledger';
|
|
152
|
+
ledger: LedgerAffected;
|
|
153
|
+
};
|
|
126
154
|
export type ProcessBroadcastResult = {
|
|
127
155
|
applied: boolean;
|
|
128
156
|
/**
|
|
@@ -150,9 +178,21 @@ export type ProcessBroadcastResult = {
|
|
|
150
178
|
* (possibly `0`) on `mutation:apply`.
|
|
151
179
|
*/
|
|
152
180
|
duplicates?: number;
|
|
181
|
+
/**
|
|
182
|
+
* Set to `'unknown-type'` when the message carried a `type` outside the
|
|
183
|
+
* known discriminated union (version skew). The frame is not applied and is
|
|
184
|
+
* logged; other branches never set this.
|
|
185
|
+
*/
|
|
186
|
+
reason?: 'unknown-type';
|
|
153
187
|
};
|
|
154
188
|
export type ProcessBroadcastParams = {
|
|
155
189
|
p2pStore: P2PStoreAPI;
|
|
190
|
+
/**
|
|
191
|
+
* Delegation store for received-grant / received-revocation handling. The
|
|
192
|
+
* delegation token and revocation rows live here (group-agnostic); the p2p
|
|
193
|
+
* store keeps only the `jti` → group edge.
|
|
194
|
+
*/
|
|
195
|
+
delegationStore: DelegationStoreAPI;
|
|
156
196
|
graphStore: GraphStoreAPI;
|
|
157
197
|
/**
|
|
158
198
|
* Engine graph internals — required to apply `mutation:apply` entries via
|
|
@@ -198,6 +238,21 @@ export type ProcessBroadcastParams = {
|
|
|
198
238
|
* Absent in tests that don't exercise the subscription path.
|
|
199
239
|
*/
|
|
200
240
|
emitter?: P2PEventEmitter;
|
|
241
|
+
/**
|
|
242
|
+
* Device-wide monotonic clock. On a newly-appended `ledger:entry` the
|
|
243
|
+
* receiver merges the entry's HLC into this clock so its own later entries
|
|
244
|
+
* sort strictly after observed ones. Optional: callers that never receive
|
|
245
|
+
* ledger entries (and existing tests) omit it and the merge is skipped.
|
|
246
|
+
*/
|
|
247
|
+
hlc?: HLC;
|
|
248
|
+
/**
|
|
249
|
+
* Resolve a group's genesis anchor, or `null` when none is available yet. A
|
|
250
|
+
* `ledger:entry` is always stored durably, but the admin-role overlay can
|
|
251
|
+
* only be projected once the authenticated epoch-0 root is known; a `null`
|
|
252
|
+
* anchor defers projection without dropping the entry. Optional so callers
|
|
253
|
+
* that never project (and existing tests) can omit it.
|
|
254
|
+
*/
|
|
255
|
+
getGroupAnchor?: (groupID: string) => Promise<GroupAnchor | null>;
|
|
201
256
|
/** Optional logger — warns on per-entry apply failures. */
|
|
202
257
|
logger?: Logger;
|
|
203
258
|
};
|
|
@@ -219,3 +274,32 @@ export type ProcessBroadcastParams = {
|
|
|
219
274
|
* payload fidelity.
|
|
220
275
|
*/
|
|
221
276
|
export declare function processBroadcast(params: ProcessBroadcastParams, message: GroupBroadcastMessage, groupID: string): Promise<ProcessBroadcastResult>;
|
|
277
|
+
/**
|
|
278
|
+
* Summary of a batched ledger catch-up apply.
|
|
279
|
+
*/
|
|
280
|
+
export type ApplyLedgerCatchupReplyResult = {
|
|
281
|
+
/** Count of entries whose verified token was newly appended to the ledger. */
|
|
282
|
+
applied: number;
|
|
283
|
+
/** Count of entries dropped because their token failed verification. */
|
|
284
|
+
rejected: number;
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* Apply a batched ledger catch-up reply from an UNTRUSTED responder. Each entry
|
|
288
|
+
* carries its own signed token, so the responder's identity is irrelevant: every
|
|
289
|
+
* token is verified independently and a forged or unsigned one is dropped without
|
|
290
|
+
* aborting the batch. Surviving entries are appended idempotently on the token
|
|
291
|
+
* digest, so a replayed or duplicated reply is a harmless no-op.
|
|
292
|
+
*
|
|
293
|
+
* A catch-up reply delivers the ledger's history out of order by construction, so
|
|
294
|
+
* after any new entry lands the projection is rebuilt authoritatively from the
|
|
295
|
+
* whole ledger (a full reproject) rather than applied incrementally. All four
|
|
296
|
+
* control projections — admin roster, circle defs, circle members, group
|
|
297
|
+
* settings — rebuild here, so a circle or settings entry delivered via catch-up
|
|
298
|
+
* materializes immediately rather than waiting for a later live entry. Projection
|
|
299
|
+
* is deferred when no genesis anchor is available yet — the entries are still
|
|
300
|
+
* stored durably.
|
|
301
|
+
*
|
|
302
|
+
* Never throws out of the per-token loop: one bad token must not abort the batch.
|
|
303
|
+
*/
|
|
304
|
+
export declare function applyLedgerCatchupReply(params: ProcessBroadcastParams, reply: BroadcastOf<'ledger-catchup:reply'>, groupID: string): Promise<ApplyLedgerCatchupReplyResult>;
|
|
305
|
+
export {};
|