@kubun/plugin-p2p 0.8.3 → 0.10.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.d.ts +4 -0
- package/lib/context/delegation.js +1 -0
- package/lib/context/group.js +1 -1
- package/lib/context/hub.d.ts +4 -0
- package/lib/context/hub.js +1 -0
- package/lib/context/join.js +1 -1
- package/lib/context/types.d.ts +28 -2
- package/lib/groups/broadcast-service.d.ts +130 -17
- package/lib/groups/broadcast-service.js +1 -1
- package/lib/groups/broadcast.d.ts +162 -5
- package/lib/groups/broadcast.js +1 -1
- package/lib/groups/events.d.ts +26 -5
- package/lib/groups/events.js +1 -1
- package/lib/groups/group-handle-registry.d.ts +90 -0
- package/lib/groups/group-handle-registry.js +1 -0
- package/lib/groups/invite-payload.d.ts +21 -1
- package/lib/groups/join-utils.d.ts +68 -2
- package/lib/groups/join-utils.js +1 -1
- package/lib/groups/manager.d.ts +26 -18
- package/lib/groups/manager.js +1 -1
- package/lib/groups/mls-codec.d.ts +7 -0
- package/lib/groups/mls-codec.js +1 -0
- package/lib/groups/mls-encryptor.d.ts +25 -0
- package/lib/groups/mls-encryptor.js +1 -0
- package/lib/groups/store-received-grant.d.ts +47 -0
- package/lib/groups/store-received-grant.js +1 -0
- package/lib/groups/store-received-revocation.d.ts +46 -0
- package/lib/groups/store-received-revocation.js +1 -0
- package/lib/groups/wire-frame.d.ts +32 -0
- package/lib/groups/wire-frame.js +1 -0
- package/lib/hub/connection-pool.d.ts +24 -0
- package/lib/hub/connection-pool.js +1 -1
- package/lib/hub/did-observing-transport.d.ts +64 -0
- package/lib/hub/did-observing-transport.js +1 -0
- package/lib/hub/errors.d.ts +28 -0
- package/lib/hub/errors.js +1 -0
- package/lib/hub/forward-remote-broadcast.d.ts +15 -0
- package/lib/hub/forward-remote-broadcast.js +1 -0
- package/lib/hub/group-channel.d.ts +37 -21
- package/lib/hub/group-channel.js +1 -1
- package/lib/hub/http-client.d.ts +17 -0
- package/lib/hub/http-client.js +1 -0
- package/lib/hub/hub-connection.d.ts +96 -0
- package/lib/hub/hub-connection.js +1 -0
- package/lib/hub/manager.d.ts +117 -0
- package/lib/hub/manager.js +1 -0
- package/lib/hub/receive-handler.d.ts +3 -6
- package/lib/hub/receive-handler.js +1 -1
- package/lib/hub/relay-manager.d.ts +92 -2
- package/lib/hub/relay-manager.js +1 -1
- package/lib/hub/send-handler.d.ts +28 -16
- package/lib/hub/send-handler.js +1 -1
- package/lib/hub/tunnel-inbox.d.ts +20 -0
- package/lib/hub/tunnel-inbox.js +1 -0
- package/lib/hub/wait-for-gate.d.ts +14 -0
- package/lib/hub/wait-for-gate.js +1 -0
- package/lib/hub/wiring.d.ts +85 -0
- package/lib/hub/wiring.js +1 -0
- package/lib/index.d.ts +102 -7
- package/lib/index.js +1 -1
- package/lib/schema.d.ts +2 -2
- package/lib/schema.js +113 -21
- package/lib/sync/broadcast-queue.d.ts +59 -0
- package/lib/sync/broadcast-queue.js +1 -0
- package/lib/sync/broadcast-sender.d.ts +52 -0
- package/lib/sync/broadcast-sender.js +1 -0
- package/lib/sync/forwarder.d.ts +97 -0
- package/lib/sync/forwarder.js +1 -0
- package/lib/sync/handlers.d.ts +20 -1
- package/lib/sync/handlers.js +1 -1
- package/lib/sync/hub-tunnel-sync-listener.d.ts +24 -0
- package/lib/sync/hub-tunnel-sync-listener.js +1 -0
- package/lib/sync/hub-tunnel-sync-provider.d.ts +36 -0
- package/lib/sync/hub-tunnel-sync-provider.js +1 -0
- package/lib/sync/merkle-apply.d.ts +41 -0
- package/lib/sync/merkle-apply.js +1 -1
- package/lib/sync/merkle-channel.d.ts +15 -0
- package/lib/sync/merkle-channel.js +1 -1
- package/lib/sync/receive-access-gate.d.ts +36 -0
- package/lib/sync/receive-access-gate.js +1 -0
- package/lib/sync/scope-resolver.d.ts +32 -0
- package/lib/sync/scope-resolver.js +1 -0
- package/lib/sync/sync-manager.d.ts +10 -0
- package/lib/sync/sync-manager.js +1 -1
- package/lib/types.d.ts +151 -1
- package/lib/util/mutex.d.ts +4 -0
- package/lib/util/mutex.js +1 -0
- package/package.json +40 -37
package/lib/types.d.ts
CHANGED
|
@@ -3,6 +3,15 @@ import type { SyncDirection, SyncProtocol } from './protocol.js';
|
|
|
3
3
|
import type { PeerConfig, PeerConfigWithID } from './sync/peer-registry.js';
|
|
4
4
|
import type { SyncScope } from './sync/sync-client.js';
|
|
5
5
|
import type { SyncEvent, SyncStatus } from './sync/sync-manager.js';
|
|
6
|
+
/**
|
|
7
|
+
* Receiver storage mode for incoming peer mutations.
|
|
8
|
+
* - `'persist'` — store every doc that passes catalog/group checks. Access
|
|
9
|
+
* enforced at query time; unreadable docs remain in DB but filtered.
|
|
10
|
+
* - `'drop'` — apply read-access check at receive time using the local
|
|
11
|
+
* peer's own DID as viewer. Mutations the local peer cannot read are
|
|
12
|
+
* not persisted.
|
|
13
|
+
*/
|
|
14
|
+
export type StoreUnreadableMode = 'persist' | 'drop';
|
|
6
15
|
export type GroupData = {
|
|
7
16
|
id: string;
|
|
8
17
|
name: string;
|
|
@@ -37,6 +46,14 @@ export type CatalogData = {
|
|
|
37
46
|
filterCriteria: string;
|
|
38
47
|
createdAt: string;
|
|
39
48
|
};
|
|
49
|
+
export type HubData = {
|
|
50
|
+
id: string;
|
|
51
|
+
label: string | null;
|
|
52
|
+
url: string;
|
|
53
|
+
serverDID: string | null;
|
|
54
|
+
createdAt: string;
|
|
55
|
+
updatedAt: string | null;
|
|
56
|
+
};
|
|
40
57
|
export type InviteToGroupData = {
|
|
41
58
|
invitePayload: string;
|
|
42
59
|
groupID: string;
|
|
@@ -76,6 +93,10 @@ export type GroupRequestContext = {
|
|
|
76
93
|
create: (input: {
|
|
77
94
|
name: string;
|
|
78
95
|
description?: string;
|
|
96
|
+
hubs?: Array<{
|
|
97
|
+
url: string;
|
|
98
|
+
serverDID?: string | null;
|
|
99
|
+
}>;
|
|
79
100
|
}) => Promise<GroupData>;
|
|
80
101
|
list: () => Promise<Array<GroupData>>;
|
|
81
102
|
get: (id: string) => Promise<GroupData | null>;
|
|
@@ -94,7 +115,15 @@ export type GroupRequestContext = {
|
|
|
94
115
|
filterCriteria: string;
|
|
95
116
|
}) => Promise<CatalogData>;
|
|
96
117
|
listCatalogs: (ownerDID?: string) => Promise<Array<CatalogData>>;
|
|
97
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Build an invite payload for a join request.
|
|
120
|
+
*
|
|
121
|
+
* `grants` are stringified write-capability JWTs the caller wants the joiner
|
|
122
|
+
* to hold immediately on join. `revocations` are signed revocation JWTs the
|
|
123
|
+
* caller wants the joiner to apply immediately — only verified ones travel;
|
|
124
|
+
* pending revocations (cap not yet known by the inviter) do not.
|
|
125
|
+
*/
|
|
126
|
+
invite: (groupID: string, joinRequest: string, grants?: Array<string>, revocations?: Array<string>) => Promise<InviteToGroupData>;
|
|
98
127
|
join: (invitePayload: string, joinRequestPayload: string) => Promise<JoinGroupData>;
|
|
99
128
|
leave: (groupID: string) => Promise<LeaveGroupData>;
|
|
100
129
|
removeMember: (groupID: string, memberDID: string) => Promise<RemoveGroupMemberData>;
|
|
@@ -108,6 +137,53 @@ export type GroupRequestContext = {
|
|
|
108
137
|
deleteCatalog: (catalogID: string) => Promise<DeleteCatalogData>;
|
|
109
138
|
deleteCircle: (circleID: string) => Promise<DeleteCircleData>;
|
|
110
139
|
removeCircleMember: (circleID: string, memberDID: string) => Promise<RemoveCircleMemberData>;
|
|
140
|
+
/**
|
|
141
|
+
* Mint a `document/write` capability granting `to` write access on resources
|
|
142
|
+
* matching `res`. Token is stored grantor-side, broadcast to the group, and
|
|
143
|
+
* returned for direct delivery.
|
|
144
|
+
*
|
|
145
|
+
* `res` is a URN. Most-specific wins; broader URNs grant strictly more:
|
|
146
|
+
* - `urn:kubun:document:<docID>` — single doc
|
|
147
|
+
* - `urn:kubun:model:<modelID>` — every doc of that model owned by the grantor
|
|
148
|
+
* - `urn:kubun:model:<interfaceID>` — every doc of every model implementing
|
|
149
|
+
* the interface (footgun: a grant on a widely-implemented interface like
|
|
150
|
+
* `Owned` or `Timestamped` becomes a near-wildcard)
|
|
151
|
+
* - `urn:kubun:user:<DID>` — every doc owned by that DID (the grantor)
|
|
152
|
+
* - `*` — every doc the grantor owns, present and future
|
|
153
|
+
*
|
|
154
|
+
* Prefer the narrowest URN that satisfies the use case. Broad grants combine
|
|
155
|
+
* with the long default `exp` (30 days) to expand the blast radius of a
|
|
156
|
+
* leaked or misdirected token.
|
|
157
|
+
*/
|
|
158
|
+
grantWriteCapability: (params: {
|
|
159
|
+
to: string;
|
|
160
|
+
res: string;
|
|
161
|
+
groupID: string;
|
|
162
|
+
expiresIn?: number;
|
|
163
|
+
}) => Promise<string>;
|
|
164
|
+
/**
|
|
165
|
+
* Revoke a previously-granted `document/write` capability by its `jti`.
|
|
166
|
+
*
|
|
167
|
+
* Revocation is binary: once a peer learns of the revocation, every
|
|
168
|
+
* mutation that authenticates via this `jti` is denied. The check is
|
|
169
|
+
* reactive, not retroactive — mutations already applied locally stay
|
|
170
|
+
* applied; only future writes carrying the revoked `jti` are gated.
|
|
171
|
+
*
|
|
172
|
+
* Only the original capability issuer may revoke it. The resolver looks up
|
|
173
|
+
* the capability locally and rejects:
|
|
174
|
+
* - `REVOCATION_CAP_UNKNOWN` when no row matches the `jti` on this peer
|
|
175
|
+
* (multi-device-grantor case, where the issuing device is not the one
|
|
176
|
+
* calling `revokeCapability`, is not yet supported).
|
|
177
|
+
* - `REVOCATION_UNAUTHORIZED` when the viewer is not the capability's
|
|
178
|
+
* issuer.
|
|
179
|
+
*
|
|
180
|
+
* Returns the boolean reported by the store: `true` when the revocation
|
|
181
|
+
* row was newly written (or materially changed), `false` on an idempotent
|
|
182
|
+
* no-op (already revoked at an equal or newer HLC).
|
|
183
|
+
*/
|
|
184
|
+
revokeCapability: (params: {
|
|
185
|
+
jti: string;
|
|
186
|
+
}) => Promise<boolean>;
|
|
111
187
|
};
|
|
112
188
|
export type SyncRequestContext = {
|
|
113
189
|
addPeer: (config: PeerConfig) => Promise<void>;
|
|
@@ -123,10 +199,79 @@ export type P2PJoinRequestContext = {
|
|
|
123
199
|
group: GroupData | null;
|
|
124
200
|
}>;
|
|
125
201
|
};
|
|
202
|
+
export type CreateHubInput = {
|
|
203
|
+
url: string;
|
|
204
|
+
label?: string | null;
|
|
205
|
+
serverDID?: string | null;
|
|
206
|
+
};
|
|
207
|
+
export type UpdateHubInput = {
|
|
208
|
+
id: string;
|
|
209
|
+
url?: string;
|
|
210
|
+
label?: string | null;
|
|
211
|
+
serverDID?: string | null;
|
|
212
|
+
};
|
|
213
|
+
export type DeleteHubData = {
|
|
214
|
+
success: boolean;
|
|
215
|
+
boundGroupIDs: Array<string>;
|
|
216
|
+
};
|
|
217
|
+
export type HubRequestContext = {
|
|
218
|
+
list: () => Promise<Array<HubData>>;
|
|
219
|
+
get: (id: string) => Promise<HubData | null>;
|
|
220
|
+
create: (input: CreateHubInput) => Promise<HubData>;
|
|
221
|
+
update: (input: UpdateHubInput) => Promise<HubData>;
|
|
222
|
+
delete: (id: string, force?: boolean) => Promise<DeleteHubData>;
|
|
223
|
+
bind: (params: {
|
|
224
|
+
hubID: string;
|
|
225
|
+
groupID: string;
|
|
226
|
+
}) => Promise<boolean>;
|
|
227
|
+
unbind: (params: {
|
|
228
|
+
hubID: string;
|
|
229
|
+
groupID: string;
|
|
230
|
+
}) => Promise<boolean>;
|
|
231
|
+
listByGroup: (groupID: string) => Promise<Array<HubData>>;
|
|
232
|
+
listGroups: (hubID: string) => Promise<Array<GroupData>>;
|
|
233
|
+
};
|
|
234
|
+
export type DelegationData = {
|
|
235
|
+
jwt: string;
|
|
236
|
+
jti: string;
|
|
237
|
+
grantor: string;
|
|
238
|
+
audience: string;
|
|
239
|
+
resource: string;
|
|
240
|
+
exp: number;
|
|
241
|
+
};
|
|
242
|
+
export type DelegationTokenCovers = {
|
|
243
|
+
modelID?: string | null;
|
|
244
|
+
docID?: string | null;
|
|
245
|
+
};
|
|
246
|
+
export type ListOwnDelegationTokensParams = {
|
|
247
|
+
viewerDID: string;
|
|
248
|
+
grantor?: string | null;
|
|
249
|
+
covers?: DelegationTokenCovers | null;
|
|
250
|
+
};
|
|
251
|
+
export type RevokedDelegationData = {
|
|
252
|
+
jti: string;
|
|
253
|
+
grantor: string;
|
|
254
|
+
audience: string;
|
|
255
|
+
revokerDID: string;
|
|
256
|
+
revokedAt: number;
|
|
257
|
+
verifiedAt: number;
|
|
258
|
+
capExp: number | null;
|
|
259
|
+
groupID: string;
|
|
260
|
+
};
|
|
261
|
+
export type ListOwnRevokedTokensParams = {
|
|
262
|
+
viewerDID: string;
|
|
263
|
+
grantor?: string | null;
|
|
264
|
+
};
|
|
265
|
+
export type DelegationRequestContext = {
|
|
266
|
+
listOwnTokens: (params: ListOwnDelegationTokensParams) => Promise<Array<DelegationData>>;
|
|
267
|
+
listOwnRevokedTokens: (params: ListOwnRevokedTokensParams) => Promise<Array<RevokedDelegationData>>;
|
|
268
|
+
};
|
|
126
269
|
export type P2PContext = {
|
|
127
270
|
group: GroupRequestContext;
|
|
128
271
|
sync: SyncRequestContext;
|
|
129
272
|
join: P2PJoinRequestContext;
|
|
273
|
+
hub: HubRequestContext;
|
|
274
|
+
delegation: DelegationRequestContext;
|
|
130
275
|
};
|
|
131
276
|
declare module '@kubun/graphql' {
|
|
132
277
|
interface PluginContextMap {
|
|
@@ -143,6 +288,11 @@ export type SyncSessionResult = {
|
|
|
143
288
|
export type SyncPluginAPI = {
|
|
144
289
|
/** Resolves when the HTTP sync transport is registered (only present when http option is enabled). */
|
|
145
290
|
syncReady?: Promise<void>;
|
|
291
|
+
/**
|
|
292
|
+
* Resolves when hub relay setup completes. `DISABLED_HUB.ready` is already
|
|
293
|
+
* resolved when the `hub` plugin option is absent.
|
|
294
|
+
*/
|
|
295
|
+
hubReady: Promise<void>;
|
|
146
296
|
addPeer(config: PeerConfig): Promise<void>;
|
|
147
297
|
removePeer(peerDID: string): Promise<void>;
|
|
148
298
|
listPeers(): Promise<Array<PeerConfigWithID>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function createMutex(){let e=Promise.resolve();return{run(t){let r=e.then(()=>t());return e=r.catch(()=>{}),r}}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubun/plugin-p2p",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"license": "see LICENSE.md",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -14,47 +14,50 @@
|
|
|
14
14
|
],
|
|
15
15
|
"sideEffects": false,
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@enkaku/async": "^0.
|
|
18
|
-
"@enkaku/capability": "^0.
|
|
19
|
-
"@enkaku/client": "^0.
|
|
20
|
-
"@enkaku/codec": "^0.
|
|
21
|
-
"@enkaku/event": "^0.
|
|
22
|
-
"@enkaku/generator": "^0.
|
|
23
|
-
"@enkaku/group": "^0.
|
|
24
|
-
"@enkaku/http-client-transport": "^0.
|
|
25
|
-
"@enkaku/http-server-transport": "^0.
|
|
26
|
-
"@enkaku/hub-protocol": "^0.
|
|
27
|
-
"@enkaku/
|
|
28
|
-
"@enkaku/
|
|
29
|
-
"@enkaku/
|
|
30
|
-
"@enkaku/
|
|
31
|
-
"@enkaku/
|
|
32
|
-
"@enkaku/
|
|
33
|
-
"@enkaku/
|
|
17
|
+
"@enkaku/async": "^0.16.0",
|
|
18
|
+
"@enkaku/capability": "^0.16.0",
|
|
19
|
+
"@enkaku/client": "^0.16.0",
|
|
20
|
+
"@enkaku/codec": "^0.16.0",
|
|
21
|
+
"@enkaku/event": "^0.16.0",
|
|
22
|
+
"@enkaku/generator": "^0.16.0",
|
|
23
|
+
"@enkaku/group": "^0.16.1",
|
|
24
|
+
"@enkaku/http-client-transport": "^0.16.0",
|
|
25
|
+
"@enkaku/http-server-transport": "^0.16.0",
|
|
26
|
+
"@enkaku/hub-protocol": "^0.16.0",
|
|
27
|
+
"@enkaku/hub-tunnel": "^0.16.0",
|
|
28
|
+
"@enkaku/protocol": "^0.16.0",
|
|
29
|
+
"@enkaku/runtime": "^0.16.0",
|
|
30
|
+
"@enkaku/schema": "^0.16.0",
|
|
31
|
+
"@enkaku/server": "^0.16.0",
|
|
32
|
+
"@enkaku/stream": "^0.16.0",
|
|
33
|
+
"@enkaku/token": "^0.16.0",
|
|
34
|
+
"@enkaku/transport": "^0.16.0",
|
|
34
35
|
"@noble/hashes": "^2.2.0",
|
|
35
36
|
"graphql": "^16.13.2",
|
|
36
|
-
"kysely": "^0.
|
|
37
|
-
"@kubun/client": "^0.
|
|
38
|
-
"@kubun/db": "^0.
|
|
39
|
-
"@kubun/
|
|
40
|
-
"@kubun/
|
|
41
|
-
"@kubun/
|
|
42
|
-
"@kubun/
|
|
43
|
-
"@kubun/
|
|
44
|
-
"@kubun/
|
|
45
|
-
"@kubun/
|
|
46
|
-
"@kubun/
|
|
47
|
-
"@kubun/
|
|
48
|
-
"@kubun/
|
|
37
|
+
"kysely": "^0.29.2",
|
|
38
|
+
"@kubun/client": "^0.10.0",
|
|
39
|
+
"@kubun/db": "^0.10.0",
|
|
40
|
+
"@kubun/store-graph": "^0.10.0",
|
|
41
|
+
"@kubun/graphql": "^0.10.0",
|
|
42
|
+
"@kubun/db-adapter": "^0.10.0",
|
|
43
|
+
"@kubun/hlc": "^0.10.0",
|
|
44
|
+
"@kubun/id": "^0.10.0",
|
|
45
|
+
"@kubun/engine": "^0.10.0",
|
|
46
|
+
"@kubun/store-p2p": "^0.10.0",
|
|
47
|
+
"@kubun/mutation": "^0.10.0",
|
|
48
|
+
"@kubun/logger": "^0.10.0",
|
|
49
|
+
"@kubun/protocol": "^0.10.0"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
|
-
"@enkaku/hub-server": "^0.
|
|
52
|
+
"@enkaku/hub-server": "^0.16.0",
|
|
52
53
|
"get-port": "^7.2.0",
|
|
53
|
-
"@kubun/db-better-sqlite": "^0.
|
|
54
|
-
"@kubun/plugin-connector": "^0.
|
|
55
|
-
"@kubun/
|
|
56
|
-
"@kubun/
|
|
57
|
-
"@kubun/
|
|
54
|
+
"@kubun/db-better-sqlite": "^0.10.0",
|
|
55
|
+
"@kubun/plugin-connector": "^0.10.0",
|
|
56
|
+
"@kubun/hub": "^0.10.0",
|
|
57
|
+
"@kubun/db-node-sqlite": "^0.10.0",
|
|
58
|
+
"@kubun/plugin-http": "^0.10.0",
|
|
59
|
+
"@kubun/plugin-rpc": "^0.10.0",
|
|
60
|
+
"@kubun/test-utils": "^0.10.0"
|
|
58
61
|
},
|
|
59
62
|
"scripts": {
|
|
60
63
|
"build:clean": "del lib",
|