@cero-base/core 1.0.1 → 1.1.1
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/package.json +1 -1
- package/src/CLAUDE.md +3 -0
- package/src/lib/errors.js +8 -0
- package/src/network/CLAUDE.md +3 -0
- package/src/network/index.js +18 -1
- package/src/rpc/CLAUDE.md +3 -0
- package/src/storage/CLAUDE.md +3 -0
- package/types/lib/errors.d.ts +6 -0
- package/types/network/index.d.ts +8 -1
package/package.json
CHANGED
package/src/CLAUDE.md
ADDED
package/src/lib/errors.js
CHANGED
|
@@ -55,6 +55,14 @@ export class CeroError extends Error {
|
|
|
55
55
|
static CLOSED(resource) {
|
|
56
56
|
return new CeroError('CLOSED', `${resource} is closed`)
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* A channel-stamped storage was opened under a different channel. Deliberately
|
|
60
|
+
* does NOT name the stored channel — that label gates the network, so leaking it
|
|
61
|
+
* in an error would hint at a realm the caller isn't on.
|
|
62
|
+
*/
|
|
63
|
+
static CHANNEL_MISMATCH() {
|
|
64
|
+
return new CeroError('CHANNEL_MISMATCH', 'storage belongs to a different channel')
|
|
65
|
+
}
|
|
58
66
|
/**
|
|
59
67
|
* Operation before `ready()` resolved.
|
|
60
68
|
*
|
package/src/network/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import ProtomuxWakeup from 'protomux-wakeup'
|
|
|
3
3
|
import ReadyResource from 'ready-resource'
|
|
4
4
|
import safetyCatch from 'safety-catch'
|
|
5
5
|
import b4a from 'b4a'
|
|
6
|
+
import { hash } from 'hypercore-crypto'
|
|
6
7
|
|
|
7
8
|
import { ACTIVE, PASSIVE } from '../lib/constants.js'
|
|
8
9
|
import { CeroError } from '../lib/errors.js'
|
|
@@ -14,6 +15,7 @@ import { Discovery } from './discovery.js'
|
|
|
14
15
|
* @property {Array<{ host: string, port: number }>} [bootstrap] Custom DHT bootstrap nodes.
|
|
15
16
|
* @property {(remotePublicKey: Uint8Array, payload: any) => boolean} [firewall] Incoming-connection filter.
|
|
16
17
|
* @property {Uint8Array[]} [relayThrough] Relay public keys to tunnel through.
|
|
18
|
+
* @property {string} [channel] Optional network-isolation label; only same-channel peers meet.
|
|
17
19
|
*
|
|
18
20
|
* @typedef {{ replicate: (stream: any) => any }} Replicable
|
|
19
21
|
*/
|
|
@@ -24,12 +26,13 @@ import { Discovery } from './discovery.js'
|
|
|
24
26
|
*/
|
|
25
27
|
export class Network extends ReadyResource {
|
|
26
28
|
/** @param {NetworkOpts} [opts] */
|
|
27
|
-
constructor({ identity, bootstrap, firewall, relayThrough } = {}) {
|
|
29
|
+
constructor({ identity, bootstrap, firewall, relayThrough, channel } = {}) {
|
|
28
30
|
super()
|
|
29
31
|
this.identity = identity || null
|
|
30
32
|
this.bootstrap = bootstrap || null
|
|
31
33
|
this.firewall = firewall || null
|
|
32
34
|
this.relayThrough = relayThrough || null
|
|
35
|
+
this.channel = channel || null
|
|
33
36
|
|
|
34
37
|
this.swarm = null
|
|
35
38
|
this.wakeup = new ProtomuxWakeup()
|
|
@@ -63,6 +66,14 @@ export class Network extends ReadyResource {
|
|
|
63
66
|
|
|
64
67
|
this.swarm = new Hyperswarm(opts)
|
|
65
68
|
|
|
69
|
+
if (this.channel) {
|
|
70
|
+
const channel = this.channel
|
|
71
|
+
const join = this.swarm.join.bind(this.swarm)
|
|
72
|
+
const leave = this.swarm.leave.bind(this.swarm)
|
|
73
|
+
this.swarm.join = (topic, opts) => join(channelTopic(topic, channel), opts)
|
|
74
|
+
this.swarm.leave = (topic) => leave(channelTopic(topic, channel))
|
|
75
|
+
}
|
|
76
|
+
|
|
66
77
|
this.swarm.on('connection', (stream, info) => {
|
|
67
78
|
if (this.closing || this.closed) {
|
|
68
79
|
stream.destroy()
|
|
@@ -226,6 +237,12 @@ function replicateInto(core, stream) {
|
|
|
226
237
|
}
|
|
227
238
|
}
|
|
228
239
|
|
|
240
|
+
// A channel re-namespaces every swarm topic so only same-channel peers meet.
|
|
241
|
+
// No channel → identity (unchanged, back-compat).
|
|
242
|
+
export function channelTopic(topic, channel) {
|
|
243
|
+
return channel ? hash([topic, b4a.from(channel)]) : topic
|
|
244
|
+
}
|
|
245
|
+
|
|
229
246
|
function isTopic(x) {
|
|
230
247
|
return b4a.isBuffer(x) && x.length === 32
|
|
231
248
|
}
|
package/types/lib/errors.d.ts
CHANGED
|
@@ -29,6 +29,12 @@ export class CeroError extends Error {
|
|
|
29
29
|
* @param {string} resource
|
|
30
30
|
*/
|
|
31
31
|
static CLOSED(resource: string): CeroError;
|
|
32
|
+
/**
|
|
33
|
+
* A channel-stamped storage was opened under a different channel. Deliberately
|
|
34
|
+
* does NOT name the stored channel — that label gates the network, so leaking it
|
|
35
|
+
* in an error would hint at a realm the caller isn't on.
|
|
36
|
+
*/
|
|
37
|
+
static CHANNEL_MISMATCH(): CeroError;
|
|
32
38
|
/**
|
|
33
39
|
* Operation before `ready()` resolved.
|
|
34
40
|
*
|
package/types/network/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
export function channelTopic(topic: any, channel: any): any;
|
|
1
2
|
/**
|
|
2
3
|
* @typedef {object} NetworkOpts
|
|
3
4
|
* @property {import('../identity/index.js').Identity} [identity] Long-lived keypair used as the swarm identity.
|
|
4
5
|
* @property {Array<{ host: string, port: number }>} [bootstrap] Custom DHT bootstrap nodes.
|
|
5
6
|
* @property {(remotePublicKey: Uint8Array, payload: any) => boolean} [firewall] Incoming-connection filter.
|
|
6
7
|
* @property {Uint8Array[]} [relayThrough] Relay public keys to tunnel through.
|
|
8
|
+
* @property {string} [channel] Optional network-isolation label; only same-channel peers meet.
|
|
7
9
|
*
|
|
8
10
|
* @typedef {{ replicate: (stream: any) => any }} Replicable
|
|
9
11
|
*/
|
|
@@ -13,7 +15,7 @@
|
|
|
13
15
|
*/
|
|
14
16
|
export class Network extends ReadyResource {
|
|
15
17
|
/** @param {NetworkOpts} [opts] */
|
|
16
|
-
constructor({ identity, bootstrap, firewall, relayThrough }?: NetworkOpts);
|
|
18
|
+
constructor({ identity, bootstrap, firewall, relayThrough, channel }?: NetworkOpts);
|
|
17
19
|
identity: import("../index.js").Identity;
|
|
18
20
|
bootstrap: {
|
|
19
21
|
host: string;
|
|
@@ -21,6 +23,7 @@ export class Network extends ReadyResource {
|
|
|
21
23
|
}[];
|
|
22
24
|
firewall: (remotePublicKey: Uint8Array, payload: any) => boolean;
|
|
23
25
|
relayThrough: Uint8Array<ArrayBufferLike>[];
|
|
26
|
+
channel: string;
|
|
24
27
|
swarm: any;
|
|
25
28
|
wakeup: any;
|
|
26
29
|
_replicateables: Set<any>;
|
|
@@ -107,6 +110,10 @@ export type NetworkOpts = {
|
|
|
107
110
|
* Relay public keys to tunnel through.
|
|
108
111
|
*/
|
|
109
112
|
relayThrough?: Uint8Array[];
|
|
113
|
+
/**
|
|
114
|
+
* Optional network-isolation label; only same-channel peers meet.
|
|
115
|
+
*/
|
|
116
|
+
channel?: string;
|
|
110
117
|
};
|
|
111
118
|
export type Replicable = {
|
|
112
119
|
replicate: (stream: any) => any;
|