@cero-base/cero 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/README.md CHANGED
@@ -49,6 +49,7 @@ Ships with TypeScript declarations (`.d.ts`) generated from JSDoc.
49
49
  | Opt | Meaning |
50
50
  | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
51
51
  | `bootstrap` | Hyperswarm bootstrap nodes. |
52
+ | `channel` | Optional network-isolation label. Peers connect only to peers on the **same** channel (it salts every swarm topic); omit it for the global network. A storage remembers its channel and refuses to reopen under a different one. Any string works. |
52
53
  | `name` / `isMobile` | Stamped on the device's `add-writer` event. |
53
54
  | `seed` / `phrase` | Restore from explicit 16-/32-byte entropy or a BIP-39 mnemonic. Without either, a stored identity is loaded if present, else a fresh one is generated. |
54
55
  | `key` | Open against an existing bee key (multi-device flow). |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cero-base/cero",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "description": "The ideal p2p API — everything is a handle, handles contain refs, refs contain rows.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -83,7 +83,7 @@
83
83
  "test": "ls test/*.test.js | xargs -P1 -n1 brittle-node"
84
84
  },
85
85
  "dependencies": {
86
- "@cero-base/core": "^1.0.1",
86
+ "@cero-base/core": "^1.1.1",
87
87
  "b4a": "^1.8.1",
88
88
  "bare-abort-controller": "^1.1.2",
89
89
  "bare-crypto": "^1.15.3",
@@ -0,0 +1,3 @@
1
+ <claude-mem-context>
2
+
3
+ </claude-mem-context>
@@ -19,7 +19,8 @@ export const refs = {
19
19
  local: {
20
20
  master: { type: 'master', kind: 'single' },
21
21
  keypair: { type: 'keypair', kind: 'single' },
22
- 'handle-keypairs': { type: 'handle-keypair' }
22
+ 'handle-keypairs': { type: 'handle-keypair' },
23
+ environment: { type: 'environment', kind: 'single' }
23
24
  }
24
25
  }
25
26
 
@@ -87,6 +87,9 @@ export const local = {
87
87
  publicKey: required(bytes),
88
88
  secretKey: required(bytes),
89
89
  encryptionKey: bytes
90
+ },
91
+ environment: {
92
+ channel: required(string)
90
93
  }
91
94
  }
92
95
 
@@ -0,0 +1,3 @@
1
+ <claude-mem-context>
2
+
3
+ </claude-mem-context>
package/src/index.js CHANGED
@@ -59,12 +59,13 @@ export { t, schema } from './lib/spec.js'
59
59
  * @property {string | null} [name] Friendly device name persisted on the identity claim.
60
60
  * @property {boolean} [isMobile] Marks this device as mobile.
61
61
  * @property {Array<{ host: string, port: number }>} [bootstrap] Custom DHT bootstrap nodes.
62
+ * @property {string} [channel] Optional network-isolation label; only same-channel peers connect.
62
63
  * @property {Uint8Array} [key] Pre-existing database key (skip bootstrap).
63
64
  * @property {Uint8Array} [encryptionKey] Pre-existing encryption key.
64
65
  * @property {Record<string, Function>} [routes] Custom RPC routes for the database dispatcher.
65
66
  * @property {(err: any) => void} [onerror] Background-task error handler.
66
67
  * @property {boolean} [recovery] Recovery flow — wipe local state and re-claim a writer slot.
67
- * @property {number} [recoveryTimeout] Max wait for writer capability during recovery.
68
+ * @property {number} [recoveryTimeout] Max wait for peer data + writer capability during recovery.
68
69
  */
69
70
 
70
71
  /**
@@ -103,7 +104,16 @@ export async function cero(dir, spec, opts = {}) {
103
104
  const identity = await resolveIdentity(opts, local)
104
105
  const writer = local ? (await local.store.get('keypair')).data : null
105
106
 
106
- network = new Network({ bootstrap: opts.bootstrap })
107
+ // Channel stamp: a storage remembers its channel; reopening it under a different channel is a
108
+ // misconfiguration that could leak data across networks, so reject it. Only when a channel is
109
+ // set (no channel = global, no stamp, unchanged).
110
+ if (local && opts.channel) {
111
+ const stored = (await local.store.get('environment')).data?.channel
112
+ if (stored == null) await local.store.set('environment', { channel: opts.channel })
113
+ else if (stored !== opts.channel) throw CeroError.CHANNEL_MISMATCH()
114
+ }
115
+
116
+ network = new Network({ bootstrap: opts.bootstrap, channel: opts.channel })
107
117
  await network.ready()
108
118
  discovery = network.join(identity.topic)
109
119
  await Promise.race([discovery.flush(), new Promise((r) => setTimeout(r, FLUSH))])
@@ -130,7 +140,8 @@ export async function cero(dir, spec, opts = {}) {
130
140
  const result = await me.bootstrap({
131
141
  name: opts.name || null,
132
142
  isMobile: opts.isMobile === true,
133
- recovering: opts.recovery === true
143
+ recovering: opts.recovery === true,
144
+ ...(opts.recoveryTimeout ? { timeout: opts.recoveryTimeout } : {})
134
145
  })
135
146
  if (local && result?.writer) {
136
147
  await local.store.set('keypair', {
@@ -192,7 +203,9 @@ export async function restore(me, phrase) {
192
203
  if (current.id === me.identity.id) return me
193
204
 
194
205
  const { _dir: dir, spec, _opts: opts } = me
195
- const { name, bootstrap, isMobile, onerror, routes, recoveryTimeout } = opts
206
+ // channel must carry over without it the recovered instance rejoins the
207
+ // global identity topic and never meets its channeled peers (recovery timeout).
208
+ const { name, bootstrap, isMobile, onerror, routes, recoveryTimeout, channel } = opts
196
209
 
197
210
  await me.close()
198
211
  await fs.promises.rm(`${dir}/main`, { recursive: true, force: true })
@@ -204,6 +217,7 @@ export async function restore(me, phrase) {
204
217
  onerror,
205
218
  routes,
206
219
  recoveryTimeout,
220
+ channel,
207
221
  phrase,
208
222
  recovery: true
209
223
  })
@@ -32,6 +32,10 @@ export namespace refs {
32
32
  'handle-keypairs': {
33
33
  type: string;
34
34
  };
35
+ environment: {
36
+ type: string;
37
+ kind: string;
38
+ };
35
39
  };
36
40
  }
37
41
  export function getHyperdbType(prim: any): any;
@@ -80,6 +80,9 @@ export const local: {
80
80
  secretKey: import("@cero-base/core").Prim;
81
81
  encryptionKey: import("@cero-base/core").Prim;
82
82
  };
83
+ environment: {
84
+ channel: import("@cero-base/core").Prim;
85
+ };
83
86
  };
84
87
  export const rpc: {
85
88
  'req-empty': {
package/types/index.d.ts CHANGED
@@ -10,12 +10,13 @@
10
10
  * @property {string | null} [name] Friendly device name persisted on the identity claim.
11
11
  * @property {boolean} [isMobile] Marks this device as mobile.
12
12
  * @property {Array<{ host: string, port: number }>} [bootstrap] Custom DHT bootstrap nodes.
13
+ * @property {string} [channel] Optional network-isolation label; only same-channel peers connect.
13
14
  * @property {Uint8Array} [key] Pre-existing database key (skip bootstrap).
14
15
  * @property {Uint8Array} [encryptionKey] Pre-existing encryption key.
15
16
  * @property {Record<string, Function>} [routes] Custom RPC routes for the database dispatcher.
16
17
  * @property {(err: any) => void} [onerror] Background-task error handler.
17
18
  * @property {boolean} [recovery] Recovery flow — wipe local state and re-claim a writer slot.
18
- * @property {number} [recoveryTimeout] Max wait for writer capability during recovery.
19
+ * @property {number} [recoveryTimeout] Max wait for peer data + writer capability during recovery.
19
20
  */
20
21
  /**
21
22
  * Open (or create) a cero handle at `dir`. Sets up storage, network and
@@ -92,6 +93,10 @@ export type CeroOpts = {
92
93
  host: string;
93
94
  port: number;
94
95
  }>;
96
+ /**
97
+ * Optional network-isolation label; only same-channel peers connect.
98
+ */
99
+ channel?: string;
95
100
  /**
96
101
  * Pre-existing database key (skip bootstrap).
97
102
  */
@@ -113,7 +118,7 @@ export type CeroOpts = {
113
118
  */
114
119
  recovery?: boolean;
115
120
  /**
116
- * Max wait for writer capability during recovery.
121
+ * Max wait for peer data + writer capability during recovery.
117
122
  */
118
123
  recoveryTimeout?: number;
119
124
  };