@meshwhisper/sdk 0.1.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 +138 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +19 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/chaff/index.d.ts +91 -0
- package/dist/chaff/index.d.ts.map +1 -0
- package/dist/chaff/index.js +268 -0
- package/dist/chaff/index.js.map +1 -0
- package/dist/cluster/index.d.ts +159 -0
- package/dist/cluster/index.d.ts.map +1 -0
- package/dist/cluster/index.js +393 -0
- package/dist/cluster/index.js.map +1 -0
- package/dist/compliance/index.d.ts +129 -0
- package/dist/compliance/index.d.ts.map +1 -0
- package/dist/compliance/index.js +315 -0
- package/dist/compliance/index.js.map +1 -0
- package/dist/crypto/index.d.ts +65 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +146 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/group/index.d.ts +155 -0
- package/dist/group/index.d.ts.map +1 -0
- package/dist/group/index.js +560 -0
- package/dist/group/index.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/namespace/index.d.ts +155 -0
- package/dist/namespace/index.d.ts.map +1 -0
- package/dist/namespace/index.js +278 -0
- package/dist/namespace/index.js.map +1 -0
- package/dist/node/index.d.ts +4 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +19 -0
- package/dist/node/index.js.map +1 -0
- package/dist/packet/index.d.ts +63 -0
- package/dist/packet/index.d.ts.map +1 -0
- package/dist/packet/index.js +244 -0
- package/dist/packet/index.js.map +1 -0
- package/dist/permissions/index.d.ts +107 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +282 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/persistence/idb-storage.d.ts +27 -0
- package/dist/persistence/idb-storage.d.ts.map +1 -0
- package/dist/persistence/idb-storage.js +75 -0
- package/dist/persistence/idb-storage.js.map +1 -0
- package/dist/persistence/index.d.ts +4 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +3 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/node-storage.d.ts +33 -0
- package/dist/persistence/node-storage.d.ts.map +1 -0
- package/dist/persistence/node-storage.js +90 -0
- package/dist/persistence/node-storage.js.map +1 -0
- package/dist/persistence/serialization.d.ts +4 -0
- package/dist/persistence/serialization.d.ts.map +1 -0
- package/dist/persistence/serialization.js +49 -0
- package/dist/persistence/serialization.js.map +1 -0
- package/dist/persistence/types.d.ts +29 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +5 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/ratchet/index.d.ts +80 -0
- package/dist/ratchet/index.d.ts.map +1 -0
- package/dist/ratchet/index.js +259 -0
- package/dist/ratchet/index.js.map +1 -0
- package/dist/reciprocity/index.d.ts +109 -0
- package/dist/reciprocity/index.d.ts.map +1 -0
- package/dist/reciprocity/index.js +311 -0
- package/dist/reciprocity/index.js.map +1 -0
- package/dist/relay/index.d.ts +87 -0
- package/dist/relay/index.d.ts.map +1 -0
- package/dist/relay/index.js +286 -0
- package/dist/relay/index.js.map +1 -0
- package/dist/routing/index.d.ts +136 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +478 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/sdk/index.d.ts +322 -0
- package/dist/sdk/index.d.ts.map +1 -0
- package/dist/sdk/index.js +1530 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sybil/index.d.ts +123 -0
- package/dist/sybil/index.d.ts.map +1 -0
- package/dist/sybil/index.js +491 -0
- package/dist/sybil/index.js.map +1 -0
- package/dist/transport/browser/index.d.ts +34 -0
- package/dist/transport/browser/index.d.ts.map +1 -0
- package/dist/transport/browser/index.js +176 -0
- package/dist/transport/browser/index.js.map +1 -0
- package/dist/transport/local/index.d.ts +57 -0
- package/dist/transport/local/index.d.ts.map +1 -0
- package/dist/transport/local/index.js +442 -0
- package/dist/transport/local/index.js.map +1 -0
- package/dist/transport/negotiator/index.d.ts +79 -0
- package/dist/transport/negotiator/index.d.ts.map +1 -0
- package/dist/transport/negotiator/index.js +289 -0
- package/dist/transport/negotiator/index.js.map +1 -0
- package/dist/transport/node/index.d.ts +56 -0
- package/dist/transport/node/index.d.ts.map +1 -0
- package/dist/transport/node/index.js +209 -0
- package/dist/transport/node/index.js.map +1 -0
- package/dist/transport/noop/index.d.ts +11 -0
- package/dist/transport/noop/index.d.ts.map +1 -0
- package/dist/transport/noop/index.js +20 -0
- package/dist/transport/noop/index.js.map +1 -0
- package/dist/transport/p2p/index.d.ts +109 -0
- package/dist/transport/p2p/index.d.ts.map +1 -0
- package/dist/transport/p2p/index.js +237 -0
- package/dist/transport/p2p/index.js.map +1 -0
- package/dist/transport/websocket/index.d.ts +89 -0
- package/dist/transport/websocket/index.d.ts.map +1 -0
- package/dist/transport/websocket/index.js +498 -0
- package/dist/transport/websocket/index.js.map +1 -0
- package/dist/transport/websocket/serialize.d.ts +5 -0
- package/dist/transport/websocket/serialize.d.ts.map +1 -0
- package/dist/transport/websocket/serialize.js +55 -0
- package/dist/transport/websocket/serialize.js.map +1 -0
- package/dist/types.d.ts +215 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/dist/x3dh/index.d.ts +120 -0
- package/dist/x3dh/index.d.ts.map +1 -0
- package/dist/x3dh/index.js +290 -0
- package/dist/x3dh/index.js.map +1 -0
- package/package.json +59 -0
- package/src/browser/index.ts +19 -0
- package/src/chaff/index.ts +340 -0
- package/src/cluster/index.ts +482 -0
- package/src/compliance/index.ts +407 -0
- package/src/crypto/index.ts +193 -0
- package/src/group/index.ts +719 -0
- package/src/index.ts +87 -0
- package/src/lz4js.d.ts +58 -0
- package/src/namespace/index.ts +336 -0
- package/src/node/index.ts +19 -0
- package/src/packet/index.ts +326 -0
- package/src/permissions/index.ts +405 -0
- package/src/persistence/idb-storage.ts +83 -0
- package/src/persistence/index.ts +3 -0
- package/src/persistence/node-storage.ts +96 -0
- package/src/persistence/serialization.ts +75 -0
- package/src/persistence/types.ts +33 -0
- package/src/ratchet/index.ts +363 -0
- package/src/reciprocity/index.ts +371 -0
- package/src/relay/index.ts +382 -0
- package/src/routing/index.ts +577 -0
- package/src/sdk/index.ts +1994 -0
- package/src/sybil/index.ts +661 -0
- package/src/transport/browser/index.ts +201 -0
- package/src/transport/local/index.ts +540 -0
- package/src/transport/negotiator/index.ts +397 -0
- package/src/transport/node/index.ts +234 -0
- package/src/transport/noop/index.ts +22 -0
- package/src/transport/p2p/index.ts +345 -0
- package/src/transport/websocket/index.ts +660 -0
- package/src/transport/websocket/serialize.ts +68 -0
- package/src/types.ts +275 -0
- package/src/x3dh/index.ts +388 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// MeshWhisper SDK — Binary Packet Codec
|
|
3
|
+
// Encodes/decodes the wire format defined in PRD section 9.
|
|
4
|
+
// ============================================================
|
|
5
|
+
import { PacketFlags } from '../types.js';
|
|
6
|
+
import lz4 from 'lz4js';
|
|
7
|
+
import { randomBytes } from 'node:crypto';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Constants
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
/** Current protocol wire version. */
|
|
12
|
+
export const PROTOCOL_VERSION = 0x01;
|
|
13
|
+
/** Fixed header size in bytes (version + flags + dest_hash + sender_eph_id + ttl + payload_length). */
|
|
14
|
+
export const HEADER_SIZE = 29;
|
|
15
|
+
/** Maximum hop count. */
|
|
16
|
+
export const MAX_TTL = 7;
|
|
17
|
+
/** Maximum encrypted payload size (uint16 max). */
|
|
18
|
+
export const MAX_PAYLOAD_SIZE = 65535;
|
|
19
|
+
// Internal field offsets within the header.
|
|
20
|
+
const OFF_VERSION = 0;
|
|
21
|
+
const OFF_FLAGS = 1;
|
|
22
|
+
const OFF_DEST_HASH = 2;
|
|
23
|
+
const OFF_SENDER_EPH_ID = 10; // 2 + 8
|
|
24
|
+
const OFF_TTL = 26; // 10 + 16
|
|
25
|
+
const OFF_PAYLOAD_LEN = 27; // 26 + 1
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Validation helpers
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
function assertUint8Array(value, expectedLen, name) {
|
|
30
|
+
if (!(value instanceof Uint8Array)) {
|
|
31
|
+
throw new TypeError(`${name} must be a Uint8Array`);
|
|
32
|
+
}
|
|
33
|
+
if (value.length !== expectedLen) {
|
|
34
|
+
throw new RangeError(`${name} must be exactly ${expectedLen} bytes, got ${value.length}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function assertValidFlags(flags) {
|
|
38
|
+
const valid = [
|
|
39
|
+
PacketFlags.DATA,
|
|
40
|
+
PacketFlags.ACK,
|
|
41
|
+
PacketFlags.CHAFF,
|
|
42
|
+
PacketFlags.HANDSHAKE,
|
|
43
|
+
PacketFlags.ROUTE_REQUEST,
|
|
44
|
+
PacketFlags.ROUTE_OFFER,
|
|
45
|
+
];
|
|
46
|
+
if (!valid.includes(flags)) {
|
|
47
|
+
throw new RangeError(`Invalid packet flags: 0x${flags.toString(16).padStart(2, '0')}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Encoding
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
/**
|
|
54
|
+
* Serialize a {@link Packet} into its binary wire representation.
|
|
55
|
+
*
|
|
56
|
+
* Layout (29-byte header + variable payload):
|
|
57
|
+
* | version (1) | flags (1) | dest_hash (8) | sender_ephemeral_id (16) | ttl (1) | payload_length (2 BE) | encrypted_payload (N) |
|
|
58
|
+
*/
|
|
59
|
+
export function encodePacket(packet) {
|
|
60
|
+
// --- Field validation ---
|
|
61
|
+
if (packet.version !== PROTOCOL_VERSION) {
|
|
62
|
+
throw new RangeError(`Unsupported protocol version: ${packet.version}`);
|
|
63
|
+
}
|
|
64
|
+
assertValidFlags(packet.flags);
|
|
65
|
+
assertUint8Array(packet.destHash, 8, 'destHash');
|
|
66
|
+
assertUint8Array(packet.senderEphemeralId, 16, 'senderEphemeralId');
|
|
67
|
+
if (!Number.isInteger(packet.ttl) || packet.ttl < 0 || packet.ttl > MAX_TTL) {
|
|
68
|
+
throw new RangeError(`ttl must be an integer between 0 and ${MAX_TTL}, got ${packet.ttl}`);
|
|
69
|
+
}
|
|
70
|
+
if (!(packet.encryptedPayload instanceof Uint8Array)) {
|
|
71
|
+
throw new TypeError('encryptedPayload must be a Uint8Array');
|
|
72
|
+
}
|
|
73
|
+
if (packet.encryptedPayload.length > MAX_PAYLOAD_SIZE) {
|
|
74
|
+
throw new RangeError(`encryptedPayload exceeds maximum size of ${MAX_PAYLOAD_SIZE} bytes (got ${packet.encryptedPayload.length})`);
|
|
75
|
+
}
|
|
76
|
+
// --- Serialise ---
|
|
77
|
+
const payloadLen = packet.encryptedPayload.length;
|
|
78
|
+
const buf = new Uint8Array(HEADER_SIZE + payloadLen);
|
|
79
|
+
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
80
|
+
buf[OFF_VERSION] = packet.version;
|
|
81
|
+
buf[OFF_FLAGS] = packet.flags;
|
|
82
|
+
buf.set(packet.destHash, OFF_DEST_HASH);
|
|
83
|
+
buf.set(packet.senderEphemeralId, OFF_SENDER_EPH_ID);
|
|
84
|
+
buf[OFF_TTL] = packet.ttl;
|
|
85
|
+
view.setUint16(OFF_PAYLOAD_LEN, payloadLen, false); // big-endian
|
|
86
|
+
buf.set(packet.encryptedPayload, HEADER_SIZE);
|
|
87
|
+
return buf;
|
|
88
|
+
}
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Decoding
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
/**
|
|
93
|
+
* Deserialize a binary buffer into a {@link Packet}.
|
|
94
|
+
*
|
|
95
|
+
* @throws on malformed input (too short, wrong version, invalid flags, length mismatch).
|
|
96
|
+
*/
|
|
97
|
+
export function decodePacket(data) {
|
|
98
|
+
if (!(data instanceof Uint8Array)) {
|
|
99
|
+
throw new TypeError('data must be a Uint8Array');
|
|
100
|
+
}
|
|
101
|
+
if (data.length < HEADER_SIZE) {
|
|
102
|
+
throw new RangeError(`Packet too short: expected at least ${HEADER_SIZE} bytes, got ${data.length}`);
|
|
103
|
+
}
|
|
104
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
105
|
+
const version = data[OFF_VERSION];
|
|
106
|
+
if (version !== PROTOCOL_VERSION) {
|
|
107
|
+
throw new RangeError(`Unsupported protocol version: ${version}`);
|
|
108
|
+
}
|
|
109
|
+
const flags = data[OFF_FLAGS];
|
|
110
|
+
assertValidFlags(flags);
|
|
111
|
+
const destHash = data.slice(OFF_DEST_HASH, OFF_DEST_HASH + 8);
|
|
112
|
+
const senderEphemeralId = data.slice(OFF_SENDER_EPH_ID, OFF_SENDER_EPH_ID + 16);
|
|
113
|
+
const ttl = data[OFF_TTL];
|
|
114
|
+
if (ttl > MAX_TTL) {
|
|
115
|
+
throw new RangeError(`ttl exceeds maximum of ${MAX_TTL}: got ${ttl}`);
|
|
116
|
+
}
|
|
117
|
+
const payloadLength = view.getUint16(OFF_PAYLOAD_LEN, false); // big-endian
|
|
118
|
+
if (data.length < HEADER_SIZE + payloadLength) {
|
|
119
|
+
throw new RangeError(`Packet truncated: header declares ${payloadLength} payload bytes, but only ${data.length - HEADER_SIZE} available`);
|
|
120
|
+
}
|
|
121
|
+
const encryptedPayload = data.slice(HEADER_SIZE, HEADER_SIZE + payloadLength);
|
|
122
|
+
return {
|
|
123
|
+
version,
|
|
124
|
+
flags,
|
|
125
|
+
destHash,
|
|
126
|
+
senderEphemeralId,
|
|
127
|
+
ttl,
|
|
128
|
+
payloadLength,
|
|
129
|
+
encryptedPayload,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
// LZ4 Compression (applied to plaintext BEFORE encryption)
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
/**
|
|
136
|
+
* Compress a plaintext payload with LZ4 (frame format).
|
|
137
|
+
*/
|
|
138
|
+
export function compressPayload(plaintext) {
|
|
139
|
+
if (!(plaintext instanceof Uint8Array)) {
|
|
140
|
+
throw new TypeError('plaintext must be a Uint8Array');
|
|
141
|
+
}
|
|
142
|
+
// lz4js.compress returns a Buffer/Uint8Array of the compressed frame.
|
|
143
|
+
const compressed = lz4.compress(plaintext);
|
|
144
|
+
return new Uint8Array(compressed);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Decompress an LZ4 compressed payload back to plaintext.
|
|
148
|
+
*/
|
|
149
|
+
export function decompressPayload(compressed) {
|
|
150
|
+
if (!(compressed instanceof Uint8Array)) {
|
|
151
|
+
throw new TypeError('compressed must be a Uint8Array');
|
|
152
|
+
}
|
|
153
|
+
const decompressed = lz4.decompress(compressed);
|
|
154
|
+
return new Uint8Array(decompressed);
|
|
155
|
+
}
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
// Packet builders
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
/**
|
|
160
|
+
* Build a DATA packet.
|
|
161
|
+
*
|
|
162
|
+
* @param destHash 8-byte truncated BLAKE3 destination hash
|
|
163
|
+
* @param senderEphId 16-byte rotating ephemeral sender identifier
|
|
164
|
+
* @param payload Encrypted payload bytes
|
|
165
|
+
* @param ttl Hop count (0-7, defaults to {@link MAX_TTL})
|
|
166
|
+
*/
|
|
167
|
+
export function createDataPacket(destHash, senderEphId, payload, ttl = MAX_TTL) {
|
|
168
|
+
return buildPacket(PacketFlags.DATA, destHash, senderEphId, payload, ttl);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Build an ACK packet (ttl fixed at 0 since ACKs are single-hop).
|
|
172
|
+
*/
|
|
173
|
+
export function createAckPacket(destHash, senderEphId, ackPayload) {
|
|
174
|
+
return buildPacket(PacketFlags.ACK, destHash, senderEphId, ackPayload, 0);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Build a CHAFF (cover-traffic) packet with random destination and payload.
|
|
178
|
+
*
|
|
179
|
+
* The payload length is randomly chosen between 32 and 256 bytes to mimic
|
|
180
|
+
* realistic traffic without being trivially distinguishable.
|
|
181
|
+
*/
|
|
182
|
+
export function createChaffPacket(senderEphId) {
|
|
183
|
+
const destHash = randomUint8Array(8);
|
|
184
|
+
const payloadLen = 32 + (randomUint8Array(1)[0] % 225); // 32..256
|
|
185
|
+
const payload = randomUint8Array(payloadLen);
|
|
186
|
+
return buildPacket(PacketFlags.CHAFF, destHash, senderEphId, payload, 0);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Build a ROUTE_REQUEST packet.
|
|
190
|
+
*/
|
|
191
|
+
export function createRouteRequestPacket(destHash, senderEphId, requestPayload) {
|
|
192
|
+
return buildPacket(PacketFlags.ROUTE_REQUEST, destHash, senderEphId, requestPayload, MAX_TTL);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Build a ROUTE_OFFER packet.
|
|
196
|
+
*/
|
|
197
|
+
export function createRouteOfferPacket(destHash, senderEphId, offerPayload) {
|
|
198
|
+
return buildPacket(PacketFlags.ROUTE_OFFER, destHash, senderEphId, offerPayload, MAX_TTL);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Build a HANDSHAKE packet.
|
|
202
|
+
*/
|
|
203
|
+
export function createHandshakePacket(destHash, senderEphId, handshakePayload) {
|
|
204
|
+
return buildPacket(PacketFlags.HANDSHAKE, destHash, senderEphId, handshakePayload, MAX_TTL);
|
|
205
|
+
}
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
// Internal helpers
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
function buildPacket(flags, destHash, senderEphId, encryptedPayload, ttl) {
|
|
210
|
+
assertUint8Array(destHash, 8, 'destHash');
|
|
211
|
+
assertUint8Array(senderEphId, 16, 'senderEphemeralId');
|
|
212
|
+
if (!Number.isInteger(ttl) || ttl < 0 || ttl > MAX_TTL) {
|
|
213
|
+
throw new RangeError(`ttl must be an integer between 0 and ${MAX_TTL}, got ${ttl}`);
|
|
214
|
+
}
|
|
215
|
+
if (!(encryptedPayload instanceof Uint8Array)) {
|
|
216
|
+
throw new TypeError('payload must be a Uint8Array');
|
|
217
|
+
}
|
|
218
|
+
if (encryptedPayload.length > MAX_PAYLOAD_SIZE) {
|
|
219
|
+
throw new RangeError(`Payload exceeds maximum size of ${MAX_PAYLOAD_SIZE} bytes (got ${encryptedPayload.length})`);
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
version: PROTOCOL_VERSION,
|
|
223
|
+
flags,
|
|
224
|
+
destHash,
|
|
225
|
+
senderEphemeralId: senderEphId,
|
|
226
|
+
ttl,
|
|
227
|
+
payloadLength: encryptedPayload.length,
|
|
228
|
+
encryptedPayload,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Generate a Uint8Array filled with cryptographically secure random bytes.
|
|
233
|
+
*/
|
|
234
|
+
function randomUint8Array(length) {
|
|
235
|
+
// Works in both Node.js and browser contexts.
|
|
236
|
+
if (typeof globalThis.crypto !== 'undefined' && typeof globalThis.crypto.getRandomValues === 'function') {
|
|
237
|
+
const buf = new Uint8Array(length);
|
|
238
|
+
globalThis.crypto.getRandomValues(buf);
|
|
239
|
+
return buf;
|
|
240
|
+
}
|
|
241
|
+
// Fallback: Node.js crypto module (already imported).
|
|
242
|
+
return new Uint8Array(randomBytes(length));
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/packet/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,wCAAwC;AACxC,4DAA4D;AAC5D,+DAA+D;AAE/D,OAAO,EAAU,WAAW,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,GAAG,MAAM,OAAO,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,qCAAqC;AACrC,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC,uGAAuG;AACvG,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAE9B,yBAAyB;AACzB,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AAEzB,mDAAmD;AACnD,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAEtC,4CAA4C;AAC5C,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,iBAAiB,GAAG,EAAE,CAAC,CAAC,QAAQ;AACtC,MAAM,OAAO,GAAG,EAAE,CAAC,CAAW,UAAU;AACxC,MAAM,eAAe,GAAG,EAAE,CAAC,CAAG,SAAS;AAEvC,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,SAAS,gBAAgB,CAAC,KAAiB,EAAE,WAAmB,EAAE,IAAY;IAC5E,IAAI,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,uBAAuB,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACjC,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,oBAAoB,WAAW,eAAe,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5F,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa;IACrC,MAAM,KAAK,GAAa;QACtB,WAAW,CAAC,IAAI;QAChB,WAAW,CAAC,GAAG;QACf,WAAW,CAAC,KAAK;QACjB,WAAW,CAAC,SAAS;QACrB,WAAW,CAAC,aAAa;QACzB,WAAW,CAAC,WAAW;KACxB,CAAC;IACF,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAAC,2BAA2B,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACzF,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,2BAA2B;IAC3B,IAAI,MAAM,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;QACxC,MAAM,IAAI,UAAU,CAAC,iCAAiC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,gBAAgB,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IACjD,gBAAgB,CAAC,MAAM,CAAC,iBAAiB,EAAE,EAAE,EAAE,mBAAmB,CAAC,CAAC;IAEpE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,OAAO,EAAE,CAAC;QAC5E,MAAM,IAAI,UAAU,CAAC,wCAAwC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,CAAC,gBAAgB,YAAY,UAAU,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,MAAM,CAAC,gBAAgB,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QACtD,MAAM,IAAI,UAAU,CAClB,4CAA4C,gBAAgB,eAAe,MAAM,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAC7G,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,MAAM,UAAU,GAAG,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC;IAClD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,WAAW,GAAG,UAAU,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IAEtE,GAAG,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC;IAClC,GAAG,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IAC9B,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACxC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;IACrD,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;IAC1B,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa;IACjE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;IAE9C,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;QAC9B,MAAM,IAAI,UAAU,CAClB,uCAAuC,WAAW,eAAe,IAAI,CAAC,MAAM,EAAE,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAEzE,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;IAClC,IAAI,OAAO,KAAK,gBAAgB,EAAE,CAAC;QACjC,MAAM,IAAI,UAAU,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9B,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAExB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,GAAG,CAAC,CAAC,CAAC;IAC9D,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,iBAAiB,GAAG,EAAE,CAAC,CAAC;IAChF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAE1B,IAAI,GAAG,GAAG,OAAO,EAAE,CAAC;QAClB,MAAM,IAAI,UAAU,CAAC,0BAA0B,OAAO,SAAS,GAAG,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa;IAE3E,IAAI,IAAI,CAAC,MAAM,GAAG,WAAW,GAAG,aAAa,EAAE,CAAC;QAC9C,MAAM,IAAI,UAAU,CAClB,qCAAqC,aAAa,4BAA4B,IAAI,CAAC,MAAM,GAAG,WAAW,YAAY,CACpH,CAAC;IACJ,CAAC;IAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,CAAC,CAAC;IAE9E,OAAO;QACL,OAAO;QACP,KAAK;QACL,QAAQ;QACR,iBAAiB;QACjB,GAAG;QACH,aAAa;QACb,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,2DAA2D;AAC3D,8EAA8E;AAE9E;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,SAAqB;IACnD,IAAI,CAAC,CAAC,SAAS,YAAY,UAAU,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,SAAS,CAAC,gCAAgC,CAAC,CAAC;IACxD,CAAC;IACD,sEAAsE;IACtE,MAAM,UAAU,GAAe,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACvD,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAsB;IACtD,IAAI,CAAC,CAAC,UAAU,YAAY,UAAU,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,YAAY,GAAe,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC5D,OAAO,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC;AACtC,CAAC;AAED,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,QAAoB,EACpB,WAAuB,EACvB,OAAmB,EACnB,MAAc,OAAO;IAErB,OAAO,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;AAC5E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAoB,EACpB,WAAuB,EACvB,UAAsB;IAEtB,OAAO,WAAW,CAAC,WAAW,CAAC,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAuB;IACvD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU;IAClE,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC7C,OAAO,WAAW,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAoB,EACpB,WAAuB,EACvB,cAA0B;IAE1B,OAAO,WAAW,CAAC,WAAW,CAAC,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;AAChG,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAoB,EACpB,WAAuB,EACvB,YAAwB;IAExB,OAAO,WAAW,CAAC,WAAW,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;AAC5F,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAoB,EACpB,WAAuB,EACvB,gBAA4B;IAE5B,OAAO,WAAW,CAAC,WAAW,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;AAC9F,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,SAAS,WAAW,CAClB,KAAkB,EAClB,QAAoB,EACpB,WAAuB,EACvB,gBAA4B,EAC5B,GAAW;IAEX,gBAAgB,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IAC1C,gBAAgB,CAAC,WAAW,EAAE,EAAE,EAAE,mBAAmB,CAAC,CAAC;IAEvD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,OAAO,EAAE,CAAC;QACvD,MAAM,IAAI,UAAU,CAAC,wCAAwC,OAAO,SAAS,GAAG,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,IAAI,CAAC,CAAC,gBAAgB,YAAY,UAAU,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,SAAS,CAAC,8BAA8B,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,gBAAgB,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QAC/C,MAAM,IAAI,UAAU,CAClB,mCAAmC,gBAAgB,eAAe,gBAAgB,CAAC,MAAM,GAAG,CAC7F,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,gBAAgB;QACzB,KAAK;QACL,QAAQ;QACR,iBAAiB,EAAE,WAAW;QAC9B,GAAG;QACH,aAAa,EAAE,gBAAgB,CAAC,MAAM;QACtC,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,MAAc;IACtC,8CAA8C;IAC9C,IAAI,OAAO,UAAU,CAAC,MAAM,KAAK,WAAW,IAAI,OAAO,UAAU,CAAC,MAAM,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;QACxG,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;QACnC,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QACvC,OAAO,GAAG,CAAC;IACb,CAAC;IACD,sDAAsD;IACtD,OAAO,IAAI,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { PermissionModel } from '../types';
|
|
2
|
+
export interface ContactContext {
|
|
3
|
+
senderId: string;
|
|
4
|
+
senderPublicKey: Uint8Array;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
introductionBy?: string;
|
|
7
|
+
transactionEvent?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface PermissionOptions {
|
|
10
|
+
customHandler?: (senderId: string, context: ContactContext) => boolean | Promise<boolean>;
|
|
11
|
+
transactionVerifier?: (senderId: string, event: string) => boolean | Promise<boolean>;
|
|
12
|
+
allowList?: Set<string>;
|
|
13
|
+
blockList?: Set<string>;
|
|
14
|
+
}
|
|
15
|
+
export interface ContactRequest {
|
|
16
|
+
id: string;
|
|
17
|
+
fromPeerId: string;
|
|
18
|
+
toPeerId: string;
|
|
19
|
+
timestamp: number;
|
|
20
|
+
status: 'pending' | 'accepted' | 'rejected';
|
|
21
|
+
}
|
|
22
|
+
export interface IntroductionRequest {
|
|
23
|
+
id: string;
|
|
24
|
+
fromPeerId: string;
|
|
25
|
+
toPeerId: string;
|
|
26
|
+
introducerPeerId: string;
|
|
27
|
+
timestamp: number;
|
|
28
|
+
status: 'pending' | 'introduced' | 'accepted' | 'rejected';
|
|
29
|
+
}
|
|
30
|
+
export declare class PermissionManager {
|
|
31
|
+
private model;
|
|
32
|
+
private readonly customHandler?;
|
|
33
|
+
private readonly transactionVerifier?;
|
|
34
|
+
private readonly contacts;
|
|
35
|
+
private readonly blocked;
|
|
36
|
+
private readonly allowed;
|
|
37
|
+
/** Peers who have sent us a contact request (mutual model). */
|
|
38
|
+
private readonly inboundRequests;
|
|
39
|
+
/** Peers we have sent a contact request to (mutual model). */
|
|
40
|
+
private readonly outboundRequests;
|
|
41
|
+
/** Introduction requests keyed by request id. */
|
|
42
|
+
private readonly introductionRequests;
|
|
43
|
+
/** Peers whose mutual contact has been confirmed (both sides accepted). */
|
|
44
|
+
private readonly mutualConfirmed;
|
|
45
|
+
/** Peers introduced to us via a trusted intermediary. */
|
|
46
|
+
private readonly introducedPeers;
|
|
47
|
+
constructor(model: PermissionModel, options?: PermissionOptions);
|
|
48
|
+
setModel(model: PermissionModel): void;
|
|
49
|
+
getModel(): PermissionModel;
|
|
50
|
+
addContact(peerId: string): void;
|
|
51
|
+
removeContact(peerId: string): void;
|
|
52
|
+
isContact(peerId: string): boolean;
|
|
53
|
+
getContacts(): string[];
|
|
54
|
+
loadContacts(contacts: string[]): void;
|
|
55
|
+
blockPeer(peerId: string): void;
|
|
56
|
+
unblockPeer(peerId: string): void;
|
|
57
|
+
isBlocked(peerId: string): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Main inbound permission check.
|
|
60
|
+
* Order: blockList -> allowList -> model-specific logic.
|
|
61
|
+
*/
|
|
62
|
+
canReceiveFrom(senderId: string, context: ContactContext): Promise<boolean>;
|
|
63
|
+
/**
|
|
64
|
+
* Outbound permission check — can we send to this recipient?
|
|
65
|
+
* Primarily relevant for the mutual model where both sides
|
|
66
|
+
* need to have each other as contacts.
|
|
67
|
+
*/
|
|
68
|
+
canSendTo(recipientId: string): Promise<boolean>;
|
|
69
|
+
/**
|
|
70
|
+
* Create a contact request to send to a peer (mutual model).
|
|
71
|
+
* The caller is responsible for transmitting the request over the wire.
|
|
72
|
+
*/
|
|
73
|
+
requestMutualContact(peerId: string): ContactRequest;
|
|
74
|
+
/**
|
|
75
|
+
* Handle an inbound contact request from a peer.
|
|
76
|
+
* Returns true if the request is accepted (i.e. we already have an
|
|
77
|
+
* outbound request to that peer, achieving mutual consent), false
|
|
78
|
+
* if the request is stored as pending.
|
|
79
|
+
*/
|
|
80
|
+
handleContactRequest(request: ContactRequest): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Explicitly confirm mutual contact with a peer.
|
|
83
|
+
* Adds the peer to contacts and the mutualConfirmed set.
|
|
84
|
+
*/
|
|
85
|
+
confirmMutualContact(peerId: string): void;
|
|
86
|
+
/**
|
|
87
|
+
* Request an introduction to a target peer through a mutual contact.
|
|
88
|
+
* The caller is responsible for transmitting the request to the introducer.
|
|
89
|
+
*/
|
|
90
|
+
requestIntroduction(targetPeerId: string, introducerPeerId: string): IntroductionRequest;
|
|
91
|
+
/**
|
|
92
|
+
* Handle an introduction request as the intermediary.
|
|
93
|
+
* Returns true if the introducer is a known contact of ours (trusted),
|
|
94
|
+
* false otherwise (the intermediary should only broker introductions
|
|
95
|
+
* between their own contacts).
|
|
96
|
+
*/
|
|
97
|
+
handleIntroductionRequest(request: IntroductionRequest): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Confirm an introduction — called on the receiving end once the
|
|
100
|
+
* introduction has been brokered by the intermediary.
|
|
101
|
+
*/
|
|
102
|
+
confirmIntroduction(request: IntroductionRequest): void;
|
|
103
|
+
private checkIntroduction;
|
|
104
|
+
private checkTransaction;
|
|
105
|
+
private checkCustom;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// MeshWhisper SDK — Contact Permissions Module
|
|
3
|
+
// Endpoint-side permission enforcement for P2P contact initiation.
|
|
4
|
+
// ============================================================
|
|
5
|
+
// --- Helpers ---
|
|
6
|
+
function generateId() {
|
|
7
|
+
const bytes = new Uint8Array(16);
|
|
8
|
+
crypto.getRandomValues(bytes);
|
|
9
|
+
return Array.from(bytes)
|
|
10
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
11
|
+
.join('');
|
|
12
|
+
}
|
|
13
|
+
// --- PermissionManager ---
|
|
14
|
+
export class PermissionManager {
|
|
15
|
+
model;
|
|
16
|
+
customHandler;
|
|
17
|
+
transactionVerifier;
|
|
18
|
+
contacts = new Set();
|
|
19
|
+
blocked = new Set();
|
|
20
|
+
allowed = new Set();
|
|
21
|
+
/** Peers who have sent us a contact request (mutual model). */
|
|
22
|
+
inboundRequests = new Map();
|
|
23
|
+
/** Peers we have sent a contact request to (mutual model). */
|
|
24
|
+
outboundRequests = new Map();
|
|
25
|
+
/** Introduction requests keyed by request id. */
|
|
26
|
+
introductionRequests = new Map();
|
|
27
|
+
/** Peers whose mutual contact has been confirmed (both sides accepted). */
|
|
28
|
+
mutualConfirmed = new Set();
|
|
29
|
+
/** Peers introduced to us via a trusted intermediary. */
|
|
30
|
+
introducedPeers = new Set();
|
|
31
|
+
constructor(model, options) {
|
|
32
|
+
this.model = model;
|
|
33
|
+
if (options?.customHandler) {
|
|
34
|
+
this.customHandler = options.customHandler;
|
|
35
|
+
}
|
|
36
|
+
if (options?.transactionVerifier) {
|
|
37
|
+
this.transactionVerifier = options.transactionVerifier;
|
|
38
|
+
}
|
|
39
|
+
if (options?.allowList) {
|
|
40
|
+
for (const id of options.allowList) {
|
|
41
|
+
this.allowed.add(id);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (options?.blockList) {
|
|
45
|
+
for (const id of options.blockList) {
|
|
46
|
+
this.blocked.add(id);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ------------------------------------------------------------------
|
|
51
|
+
// Model switching
|
|
52
|
+
// ------------------------------------------------------------------
|
|
53
|
+
setModel(model) {
|
|
54
|
+
this.model = model;
|
|
55
|
+
}
|
|
56
|
+
getModel() {
|
|
57
|
+
return this.model;
|
|
58
|
+
}
|
|
59
|
+
// ------------------------------------------------------------------
|
|
60
|
+
// Contact management
|
|
61
|
+
// ------------------------------------------------------------------
|
|
62
|
+
addContact(peerId) {
|
|
63
|
+
this.contacts.add(peerId);
|
|
64
|
+
}
|
|
65
|
+
removeContact(peerId) {
|
|
66
|
+
this.contacts.delete(peerId);
|
|
67
|
+
this.mutualConfirmed.delete(peerId);
|
|
68
|
+
}
|
|
69
|
+
isContact(peerId) {
|
|
70
|
+
return this.contacts.has(peerId);
|
|
71
|
+
}
|
|
72
|
+
getContacts() {
|
|
73
|
+
return Array.from(this.contacts);
|
|
74
|
+
}
|
|
75
|
+
loadContacts(contacts) {
|
|
76
|
+
for (const id of contacts)
|
|
77
|
+
this.contacts.add(id);
|
|
78
|
+
}
|
|
79
|
+
blockPeer(peerId) {
|
|
80
|
+
this.blocked.add(peerId);
|
|
81
|
+
}
|
|
82
|
+
unblockPeer(peerId) {
|
|
83
|
+
this.blocked.delete(peerId);
|
|
84
|
+
}
|
|
85
|
+
isBlocked(peerId) {
|
|
86
|
+
return this.blocked.has(peerId);
|
|
87
|
+
}
|
|
88
|
+
// ------------------------------------------------------------------
|
|
89
|
+
// Permission checks
|
|
90
|
+
// ------------------------------------------------------------------
|
|
91
|
+
/**
|
|
92
|
+
* Main inbound permission check.
|
|
93
|
+
* Order: blockList -> allowList -> model-specific logic.
|
|
94
|
+
*/
|
|
95
|
+
async canReceiveFrom(senderId, context) {
|
|
96
|
+
// Always deny blocked peers.
|
|
97
|
+
if (this.blocked.has(senderId)) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
// Always allow explicitly allowed peers.
|
|
101
|
+
if (this.allowed.has(senderId)) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
// Existing contacts are always permitted regardless of model.
|
|
105
|
+
if (this.contacts.has(senderId)) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
switch (this.model) {
|
|
109
|
+
case 'open':
|
|
110
|
+
return true;
|
|
111
|
+
case 'mutual':
|
|
112
|
+
return this.mutualConfirmed.has(senderId);
|
|
113
|
+
case 'introduction':
|
|
114
|
+
return this.introducedPeers.has(senderId) || this.checkIntroduction(senderId, context);
|
|
115
|
+
case 'transactional':
|
|
116
|
+
return this.checkTransaction(senderId, context);
|
|
117
|
+
case 'custom':
|
|
118
|
+
return this.checkCustom(senderId, context);
|
|
119
|
+
default:
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Outbound permission check — can we send to this recipient?
|
|
125
|
+
* Primarily relevant for the mutual model where both sides
|
|
126
|
+
* need to have each other as contacts.
|
|
127
|
+
*/
|
|
128
|
+
async canSendTo(recipientId) {
|
|
129
|
+
// Never send to blocked peers.
|
|
130
|
+
if (this.blocked.has(recipientId)) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
// Always allowed peers.
|
|
134
|
+
if (this.allowed.has(recipientId)) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
switch (this.model) {
|
|
138
|
+
case 'open':
|
|
139
|
+
return true;
|
|
140
|
+
case 'mutual':
|
|
141
|
+
// Can only send if mutual contact has been confirmed or they are
|
|
142
|
+
// already a known contact.
|
|
143
|
+
return this.contacts.has(recipientId) || this.mutualConfirmed.has(recipientId);
|
|
144
|
+
case 'introduction':
|
|
145
|
+
return (this.contacts.has(recipientId) || this.introducedPeers.has(recipientId));
|
|
146
|
+
case 'transactional':
|
|
147
|
+
// For outbound in transactional model, allow if they are a contact.
|
|
148
|
+
return this.contacts.has(recipientId);
|
|
149
|
+
case 'custom':
|
|
150
|
+
// Custom model defers to the handler for inbound only;
|
|
151
|
+
// outbound is permitted to any non-blocked peer.
|
|
152
|
+
return true;
|
|
153
|
+
default:
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// ------------------------------------------------------------------
|
|
158
|
+
// Mutual model logic
|
|
159
|
+
// ------------------------------------------------------------------
|
|
160
|
+
/**
|
|
161
|
+
* Create a contact request to send to a peer (mutual model).
|
|
162
|
+
* The caller is responsible for transmitting the request over the wire.
|
|
163
|
+
*/
|
|
164
|
+
requestMutualContact(peerId) {
|
|
165
|
+
const request = {
|
|
166
|
+
id: generateId(),
|
|
167
|
+
fromPeerId: '', // Will be filled by the caller with own peer ID
|
|
168
|
+
toPeerId: peerId,
|
|
169
|
+
timestamp: Date.now(),
|
|
170
|
+
status: 'pending',
|
|
171
|
+
};
|
|
172
|
+
this.outboundRequests.set(peerId, request);
|
|
173
|
+
return request;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Handle an inbound contact request from a peer.
|
|
177
|
+
* Returns true if the request is accepted (i.e. we already have an
|
|
178
|
+
* outbound request to that peer, achieving mutual consent), false
|
|
179
|
+
* if the request is stored as pending.
|
|
180
|
+
*/
|
|
181
|
+
handleContactRequest(request) {
|
|
182
|
+
if (this.blocked.has(request.fromPeerId)) {
|
|
183
|
+
request.status = 'rejected';
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
this.inboundRequests.set(request.fromPeerId, request);
|
|
187
|
+
// If we already sent a request to this peer, auto-confirm mutual contact.
|
|
188
|
+
if (this.outboundRequests.has(request.fromPeerId)) {
|
|
189
|
+
request.status = 'accepted';
|
|
190
|
+
const outbound = this.outboundRequests.get(request.fromPeerId);
|
|
191
|
+
outbound.status = 'accepted';
|
|
192
|
+
this.confirmMutualContact(request.fromPeerId);
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Explicitly confirm mutual contact with a peer.
|
|
199
|
+
* Adds the peer to contacts and the mutualConfirmed set.
|
|
200
|
+
*/
|
|
201
|
+
confirmMutualContact(peerId) {
|
|
202
|
+
this.mutualConfirmed.add(peerId);
|
|
203
|
+
this.contacts.add(peerId);
|
|
204
|
+
}
|
|
205
|
+
// ------------------------------------------------------------------
|
|
206
|
+
// Introduction model logic
|
|
207
|
+
// ------------------------------------------------------------------
|
|
208
|
+
/**
|
|
209
|
+
* Request an introduction to a target peer through a mutual contact.
|
|
210
|
+
* The caller is responsible for transmitting the request to the introducer.
|
|
211
|
+
*/
|
|
212
|
+
requestIntroduction(targetPeerId, introducerPeerId) {
|
|
213
|
+
const request = {
|
|
214
|
+
id: generateId(),
|
|
215
|
+
fromPeerId: '', // Will be filled by the caller with own peer ID
|
|
216
|
+
toPeerId: targetPeerId,
|
|
217
|
+
introducerPeerId,
|
|
218
|
+
timestamp: Date.now(),
|
|
219
|
+
status: 'pending',
|
|
220
|
+
};
|
|
221
|
+
this.introductionRequests.set(request.id, request);
|
|
222
|
+
return request;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Handle an introduction request as the intermediary.
|
|
226
|
+
* Returns true if the introducer is a known contact of ours (trusted),
|
|
227
|
+
* false otherwise (the intermediary should only broker introductions
|
|
228
|
+
* between their own contacts).
|
|
229
|
+
*/
|
|
230
|
+
handleIntroductionRequest(request) {
|
|
231
|
+
if (this.blocked.has(request.fromPeerId)) {
|
|
232
|
+
request.status = 'rejected';
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
// The intermediary should know both parties as contacts.
|
|
236
|
+
const knowsSender = this.contacts.has(request.fromPeerId);
|
|
237
|
+
const knowsTarget = this.contacts.has(request.toPeerId);
|
|
238
|
+
if (knowsSender && knowsTarget) {
|
|
239
|
+
request.status = 'introduced';
|
|
240
|
+
this.introductionRequests.set(request.id, request);
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
request.status = 'rejected';
|
|
244
|
+
this.introductionRequests.set(request.id, request);
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Confirm an introduction — called on the receiving end once the
|
|
249
|
+
* introduction has been brokered by the intermediary.
|
|
250
|
+
*/
|
|
251
|
+
confirmIntroduction(request) {
|
|
252
|
+
request.status = 'accepted';
|
|
253
|
+
this.introductionRequests.set(request.id, request);
|
|
254
|
+
this.introducedPeers.add(request.fromPeerId);
|
|
255
|
+
this.contacts.add(request.fromPeerId);
|
|
256
|
+
}
|
|
257
|
+
// ------------------------------------------------------------------
|
|
258
|
+
// Private model-specific checks
|
|
259
|
+
// ------------------------------------------------------------------
|
|
260
|
+
checkIntroduction(senderId, context) {
|
|
261
|
+
// If the context carries a valid introduction reference, check it.
|
|
262
|
+
if (context.introductionBy) {
|
|
263
|
+
// The introducer must be one of our contacts.
|
|
264
|
+
return this.contacts.has(context.introductionBy);
|
|
265
|
+
}
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
async checkTransaction(senderId, context) {
|
|
269
|
+
if (!this.transactionVerifier || !context.transactionEvent) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
return this.transactionVerifier(senderId, context.transactionEvent);
|
|
273
|
+
}
|
|
274
|
+
async checkCustom(senderId, context) {
|
|
275
|
+
if (!this.customHandler) {
|
|
276
|
+
// No custom handler configured — deny by default for safety.
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
return this.customHandler(senderId, context);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"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"}
|