nedb-engine 2.0.5 → 2.0.31

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  # NEDB
4
4
 
5
- **Hash-chained · time-traveling · bi-temporal · causally-provable embedded database.**
5
+ **Content-addressed Merkle DAG · Hash-chained · Time-traveling · Bi-temporal · Causally-provable embedded database.**
6
6
 
7
7
  Replay-protected · idempotent · relational · filterable · sortable · searchable · concurrent.
8
8
  One Rust core → ships to **PyPI** and **npm** from a single source.
@@ -10,6 +10,8 @@ One Rust core → ships to **PyPI** and **npm** from a single source.
10
10
  [![PyPI](https://img.shields.io/pypi/v/nedb-engine?label=PyPI&color=6366f1)](https://pypi.org/project/nedb-engine/)
11
11
  [![npm](https://img.shields.io/npm/v/nedb-engine?label=npm&color=00d4ff)](https://www.npmjs.com/package/nedb-engine)
12
12
  [![Tests](https://img.shields.io/badge/tests-266%20passing-34d399)](https://github.com/Eth-Interchained/nedb/actions)
13
+ [![nedb-engine-client PyPI](https://img.shields.io/pypi/v/nedb-engine-client?label=nedb-engine-client&color=34d399)](https://pypi.org/project/nedb-engine-client/)
14
+ [![nedb-engine-client npm](https://img.shields.io/npm/v/nedb-engine-client?label=nedb-engine-client&color=34d399)](https://www.npmjs.com/package/nedb-engine-client)
13
15
 
14
16
  **[Studio → studio.interchained.org](https://studio.interchained.org)** · **[nedb.aiassist.net](https://nedb.aiassist.net)**
15
17
 
@@ -17,6 +19,47 @@ One Rust core → ships to **PyPI** and **npm** from a single source.
17
19
 
18
20
  ---
19
21
 
22
+ ## v2 — The DAG Engine (current stable: 2.0.27)
23
+
24
+ NEDB v2 replaces the append-only log (AOF) with a **content-addressed Merkle DAG**. Every document version is an immutable, BLAKE2b-verified object. Nothing is ever overwritten. As of **v2.0.27**, restarts after the first open are **O(1) warm starts** (driven by a `MANIFEST` of `seq` + Merkle head), the **cold scan is deferred** so the daemon accepts connections immediately, and a new **`GET /events` SSE endpoint** streams scan progress + per-write events live.
25
+
26
+ ```bash
27
+ # Run the v2 DAG engine — ships inside pip install nedb-engine
28
+ nedbd --dag --data ./data
29
+ # or
30
+ NEDBD_DAG=1 NEDB_TMK=<32-byte-hex> nedbd --data ./data
31
+
32
+ curl http://127.0.0.1:7070/health
33
+ # {"ok":true,"version":"2.0.27","service":"nedbd","engine":"dag","startup_ready":true,"encrypted":true}
34
+
35
+ # Tail the live event stream (new in v2.0.27)
36
+ curl http://127.0.0.1:7070/events
37
+ # event: scan data: {"objects":730000,"of":1310703,"rate":21043,"eta_s":28}
38
+ # event: ready data: {"seq":1310703,"head":"b2:9c14e07a…"}
39
+ # event: write data: {"seq":1310704,"coll":"beliefs","head":"b2:7af3c11e…"}
40
+ ```
41
+
42
+ | Property | v2 DAG | v1 AOF |
43
+ |---|:---:|:---:|
44
+ | Uncorruptable (atomic writes, hash-verified reads) | ✅ | ⚠️ |
45
+ | O(1) warm start via MANIFEST (no scan, no replay) | ✅ | ❌ |
46
+ | Deferred cold scan (socket open immediately) | ✅ | ❌ |
47
+ | O(1) incremental Merkle head (never recomputed) | ✅ | ❌ |
48
+ | Parallel writes (no global lock) | ✅ | ❌ |
49
+ | BLAKE2b Merkle head on every response | ✅ | ❌ |
50
+ | IdIndex sharded across 256 subdirectories | ✅ | ❌ |
51
+ | TCP_NODELAY (no 40–200 ms loopback Nagle delay) | ✅ | ❌ |
52
+ | `GET /events` SSE log stream | ✅ | ❌ |
53
+ | Tombstone deletes (history preserved) | ✅ | ✅ |
54
+ | Auto-migrates v1 AOF → v2 DAG on startup | ✅ | — |
55
+ | Same HTTP API — Vision, Studio, all clients unchanged | ✅ | ✅ |
56
+
57
+ **v1 AOF engine is still shipped and unchanged** — `nedbd` (no flag) runs v1.
58
+
59
+ **Production status:** [vision.interchained.org](https://vision.interchained.org) is live on v2.0.27 — **1,310,703 sequences** indexed in the Vision database, AES-256-GCM encrypted at rest, at block height **620,989**.
60
+
61
+ ---
62
+
20
63
  ## What makes NEDB different
21
64
 
22
65
  Every database stores *what*. NEDB stores *what*, *when*, *when it was true*, and *why* — all sealed in a cryptographic hash chain that proves none of it was tampered with.
@@ -173,11 +216,31 @@ db.seq(); // → BigInt
173
216
  nedbd runs NEDB as a long-lived process with an HTTP/JSON API and an optional RESP2 wire protocol. Built on a **single-writer group-commit sequencer** — parallel reads, batched durable writes, one hash-chain per database, zero write-write races.
174
217
 
175
218
  ```bash
176
- nedbd # :7070, data ./nedb-data
219
+ nedbd # :7070, data ./nedb-data (v1 AOF engine)
220
+ nedbd --dag --data ./data # v2 DAG engine (or NEDBD_DAG=1)
177
221
  NEDBD_RESP2_PORT=6380 nedbd # also speak RESP2 (redis-cli compatible)
178
222
  nedbd --log-level 2 # 0=errors 1=requests 2=deploy 3=verbose
223
+
224
+ # Live event stream (new in v2.0.27) — SSE: scan progress, ready, per-write head
225
+ curl http://127.0.0.1:7070/events
179
226
  ```
180
227
 
228
+ ### Startup modes (v2.0.27)
229
+
230
+ - **Warm start** — every restart after the first open reads the `MANIFEST` file and restores `seq` + Merkle `head` in **O(1)**. No scan, no replay, independent of dataset size. Boots in milliseconds.
231
+ - **Cold start** — first open of an existing dataset spawns the integrity scan in a background thread *and accepts connections immediately*. Reads serve instantly from the content-addressed DAG; writes return `HTTP 503 startup in progress` until the `startup_ready` gate flips. Progress (objects, rate, ETA) streams over `GET /events`.
232
+
233
+ ### Environment variables
234
+
235
+ | Variable | Default | Description |
236
+ |---|---|---|
237
+ | `NEDBD_DAG` | `0` | Set `1` to launch the v2 DAG engine (`nedbd-v2`). Same as `--dag`. |
238
+ | `NEDBD_HOST` | `127.0.0.1` | Bind address. **v2.0.27** defaults to loopback (was `0.0.0.0`) — security hardening fix. Set explicitly to `0.0.0.0` to expose. |
239
+ | `NEDBD_PORT` | `7070` | HTTP bind port. |
240
+ | `NEDBD_TOKEN` | unset | Optional bearer token; required on every `/v1/*` request when set. |
241
+ | `NEDB_TMK` | unset | 32-byte hex AES-256-GCM at-rest encryption key. |
242
+ | `NEDBD_DATA` | `./nedb-data` | Root directory. v2 creates `dag/`, IdIndex sharded across **256 subdirectories**, and a small `MANIFEST` file. |
243
+
181
244
  ```bash
182
245
  # Create a database with seed data and relations
183
246
  curl -X POST :7070/v1/databases -d '{
@@ -233,15 +296,37 @@ db.query('FROM policy AS OF 200 VALID AS OF "2024-02-15"')
233
296
 
234
297
  ---
235
298
 
236
- ## Performance (v1.0.x · Rust native · Linux x86_64 VPS)
299
+ ## Performance
300
+
301
+ **v2 DAG Rust server (v2.0.27, Intel iMac — 10k writes / 100k reads / 30k objects, AES-256-GCM on):**
302
+
303
+ | Operation | Throughput | p50 | p99 |
304
+ |---|---|---|---|
305
+ | Sequential writes | **418 ops/s** | 2.3 ms | 3.3 ms |
306
+ | Point-lookup reads | **478 ops/s** | 2.0 ms | 3.0 ms |
307
+ | ORDER BY queries | **489 ops/s** | 1.8 ms | 4.3 ms |
308
+ | Batch writes (500 ops/req) | **1,104 ops/s** | 0.9 ms | 1.2 ms |
309
+ | Tamper-verify (30k objects) | ~21,000 BLAKE2b/sec | — | 1.38 s total |
310
+
311
+ p99 latencies hold because of `TCP_NODELAY` on the axum listener — without it macOS loopback adds the Nagle algorithm's 40–200 ms delay on small writes.
312
+
313
+ **v1 Python server (baseline — single-threaded AOF):**
237
314
 
238
- | Operation | Throughput | Notes |
315
+ | Operation | Throughput | p99 latency |
239
316
  |---|---|---|
240
- | PUT (Rust napi, per-op FFI) | ~70K/s | FFI-bound; batch path: ~15K writes/s group-commit |
241
- | GET (Rust napi, per-op FFI) | ~330K/s | FFI-bound |
242
- | NQL query (Rust engine) | ~23 µs | faster than pure-Python (~120 µs) |
243
- | Python PUT (AOF + fsync) | ~7K/s | Durable, per-op |
244
- | Python GET (in-process) | ~1.3M/s | Zero socket hop |
317
+ | Sequential PUT | ~23/s | 44 ms |
318
+ | Concurrent PUT (16 workers) | ~92/s | 48 ms |
319
+ | Batch PUT (500 ops/request) | ~520 ops/s | 1.9 ms/op |
320
+ | Point-lookup read (NQL) | ~23/s | 44 ms |
321
+ | Rust napi PUT (FFI) | ~70K/s | |
322
+ | Rust napi GET (FFI) | ~330K/s | — |
323
+
324
+ Reproduce with the included benchmark:
325
+
326
+ ```bash
327
+ NEDBD_DAG=1 nedbd --data /tmp/perf &
328
+ python3 tests/test_dag_perf.py --n 10000 --reads 100000
329
+ ```
245
330
 
246
331
  ---
247
332
 
@@ -271,16 +356,49 @@ Encryption: AES-256-GCM at-rest (TMK/DEK double-envelope)
271
356
 
272
357
  ---
273
358
 
359
+ ## nedb-client — lightweight HTTP client
360
+
361
+ Connect to any running nedbd instance from Python or TypeScript without embedding the engine:
362
+
363
+ ```bash
364
+ pip install nedb-engine-client # async Python
365
+ npm install nedb-engine-client # TypeScript / Node.js 18+
366
+ ```
367
+
368
+ ```python
369
+ from nedb_client import NedbClient
370
+
371
+ async with NedbClient("http://127.0.0.1:7070", db="mydb") as db:
372
+ await db.put("blocks", "618000", {"height": 618000})
373
+ rows = await db.query("FROM blocks ORDER BY height DESC LIMIT 10")
374
+ head = await db.head() # BLAKE2b Merkle root — changes on every write
375
+ ok = await db.verify() # tamper-evidence check across all objects
376
+ ```
377
+
378
+ ```typescript
379
+ import { NedbClient } from "nedb-engine-client";
380
+ const db = new NedbClient({ url: "http://127.0.0.1:7070", db: "mydb" });
381
+ await db.put("blocks", "618000", { height: 618000 });
382
+ const rows = await db.query("FROM blocks LIMIT 10");
383
+ ```
384
+
385
+ ---
386
+
274
387
  ## Repo layout
275
388
 
276
389
  ```
277
390
  python/nedb/ reference engine (pure Python — always-works baseline)
278
391
  rust/
279
- nedb-core/ production Rust engine (shared by both runtimes)
392
+ nedb-core/ v1 production Rust engine (shared by both runtimes)
280
393
  nedb-py/ maturin PyO3 binding → PyPI native wheels
281
394
  nedb-node/ napi-rs binding → npm native addons
282
- tests/ engine + concurrent + causal + bitemporal + deploy tests
395
+ nedb-v2/ v2 DAG engine (tokio + axum + BLAKE2b DAG)
396
+ client/
397
+ python/ nedb-client — async Python HTTP client (pip install nedb-engine-client)
398
+ node/ nedb-client — TypeScript HTTP client (npm install nedb-client)
399
+ tests/ engine + concurrent + causal + bitemporal + deploy + perf benchmarks
283
400
  examples/ resp2_python.py resp2_demo.sh
401
+ docs/ index.html reference.html SPEC.md
284
402
  ```
285
403
 
286
404
  ---
@@ -297,7 +415,17 @@ examples/ resp2_python.py resp2_demo.sh
297
415
  - [x] SQL / Redis / MongoDB compatibility adapters
298
416
  - [x] RESP2 wire protocol (redis-cli / redis-benchmark compatible)
299
417
  - [x] Rust native core — napi-rs (npm) + maturin PyO3 (PyPI)
300
- - [x] Self-healing chains (auto-repair structural gaps, detect real tampering)
418
+ - [x] Self-healing AOF auto-truncates corrupt tail on startup, never hangs
419
+ - [x] **v2 DAG engine** — content-addressed Merkle DAG, atomic writes, instant cold start
420
+ - [x] **`nedbd --dag`** — one flag switches to v2 Rust engine; v1 untouched
421
+ - [x] **BLAKE2b Merkle head** — tamper-evident root on every response
422
+ - [x] **Tombstone deletes** — history preserved in DAG, live id removed from index
423
+ - [x] **Auto-migration** — v1 AOF → v2 DAG on first `--dag` startup
424
+ - [x] **nedb-client** — async Python + TypeScript HTTP client (`pip/npm install nedb-client`)
425
+ - [x] **Intel Mac support** — native wheels for `aarch64` + `x86_64` Apple Darwin
426
+ - [ ] In-memory DAG mode — `Db::in_memory()` for zero-disk ephemeral sessions
427
+ - [ ] PyO3 + napi-rs bindings updated to v2 DAG API
428
+ - [ ] NEDB Studio DAG mode toggle
301
429
  - [ ] Merkle inclusion proofs — prove a document existed at a specific time to a third party
302
430
  - [ ] Git-style branching — fork database state, experiment, merge or discard
303
431
  - [ ] Agent Memory SDK — `Memory.remember()` / `Memory.recall()` / `Memory.trace()`
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nedb-engine",
3
- "version": "2.0.5",
3
+ "version": "2.0.31",
4
4
  "description": "NEDB — hash-chained, time-traveling, bi-temporal embedded database with Rust native core. SQL, Redis, MongoDB adapters. Causal Write Provenance. RESP2 wire protocol.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
Binary file