@push.rocks/smartdb 2.7.0 → 2.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartdb",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "private": false,
5
5
  "description": "A MongoDB-compatible embedded database server with wire protocol support, backed by a high-performance Rust engine.",
6
6
  "exports": {
package/readme.md CHANGED
@@ -248,6 +248,64 @@ const server = new SmartdbServer({
248
248
  persistPath: './data/snapshot.json',
249
249
  persistIntervalMs: 30000, // Save every 30s
250
250
  });
251
+
252
+ // TLS transport for TCP mode
253
+ const tlsServer = new SmartdbServer({
254
+ port: 27017,
255
+ tls: {
256
+ enabled: true,
257
+ certPath: './certs/server.pem',
258
+ keyPath: './certs/server.key',
259
+ // caPath: './certs/client-ca.pem',
260
+ // requireClientCert: true, // Enables mTLS client certificate checks
261
+ },
262
+ });
263
+
264
+ // SCRAM-SHA-256 authentication
265
+ const secureServer = new SmartdbServer({
266
+ port: 27017,
267
+ auth: {
268
+ enabled: true,
269
+ usersPath: './data/smartdb-users.json', // Optional: persists derived SCRAM credentials
270
+ users: [
271
+ {
272
+ username: 'root',
273
+ password: 'change-me',
274
+ database: 'admin',
275
+ roles: ['root'],
276
+ },
277
+ ],
278
+ },
279
+ });
280
+ ```
281
+
282
+ When `auth.enabled` is true, protected commands require successful SCRAM-SHA-256 authentication through the official MongoDB driver:
283
+
284
+ ```typescript
285
+ const client = new MongoClient('mongodb://root:change-me@127.0.0.1:27017/admin?authSource=admin', {
286
+ directConnection: true,
287
+ });
288
+ await client.connect();
289
+ ```
290
+
291
+ TLS is available for TCP listeners. `getConnectionUri()` includes `?tls=true` when TLS is enabled; pass the trusted CA to the MongoDB driver with `tlsCAFile`, `ca`, or `secureContext`.
292
+
293
+ Authentication verifies SCRAM credentials, denies unauthenticated commands, and enforces command-level built-in roles for supported operations. `connectionStatus` reports the authenticated users and roles for the current socket.
294
+
295
+ Supported built-in role names are `root`, `read`, `readWrite`, `dbAdmin`, `userAdmin`, `clusterMonitor`, plus `readAnyDatabase`, `readWriteAnyDatabase`, `dbAdminAnyDatabase`, and `userAdminAnyDatabase`. When `usersPath` is set, SmartDB persists SCRAM credential material atomically and does not store plaintext passwords.
296
+
297
+ Single-node transactions are supported through official MongoDB driver sessions. Writes with `startTransaction` and `autocommit: false` are buffered per logical session, reads inside the transaction see the buffered overlay, `commitTransaction` applies the write set with conflict checks, and `abortTransaction` discards it.
298
+
299
+ Basic user management commands are available for authenticated users with `root` or `userAdmin` privileges:
300
+
301
+ ```typescript
302
+ await client.db('admin').command({
303
+ createUser: 'reader',
304
+ pwd: 'readpass',
305
+ roles: [{ role: 'read', db: 'myapp' }],
306
+ });
307
+
308
+ await client.db('admin').command({ usersInfo: 'reader' });
251
309
  ```
252
310
 
253
311
  #### Methods & Properties
@@ -261,7 +319,7 @@ const server = new SmartdbServer({
261
319
  | `port` | `number` | Configured port (TCP mode) |
262
320
  | `host` | `string` | Configured host (TCP mode) |
263
321
  | `socketPath` | `string \| undefined` | Socket path (socket mode) |
264
- | `getMetrics()` | `Promise<ISmartDbMetrics>` | Server metrics (db/collection counts, uptime) |
322
+ | `getMetrics()` | `Promise<ISmartDbMetrics>` | Server metrics (db/collection counts, sessions, transactions, auth, uptime) |
265
323
  | `getOpLog(params?)` | `Promise<IOpLogResult>` | Query oplog entries with optional filters |
266
324
  | `getOpLogStats()` | `Promise<IOpLogStats>` | Aggregate oplog statistics |
267
325
  | `revertToSeq(seq, dryRun?)` | `Promise<IRevertResult>` | Revert to a specific oplog sequence |
@@ -475,7 +533,7 @@ const names = await collection.distinct('name');
475
533
  | **Aggregation** | `aggregate`, `count`, `distinct` |
476
534
  | **Indexes** | `createIndexes`, `dropIndexes`, `listIndexes` |
477
535
  | **Sessions** | `startSession`, `endSessions` |
478
- | **Transactions** | `commitTransaction`, `abortTransaction` |
536
+ | **Transactions** | `startTransaction`, `commitTransaction`, `abortTransaction` through driver sessions |
479
537
  | **Admin** | `ping`, `listDatabases`, `listCollections`, `drop`, `dropDatabase`, `create`, `serverStatus`, `buildInfo`, `dbStats`, `collStats`, `connectionStatus`, `currentOp`, `renameCollection` |
480
538
 
481
539
  Compatible with wire protocol versions 0–21 (driver versions 3.6 through 7.0).
@@ -484,7 +542,7 @@ Compatible with wire protocol versions 0–21 (driver versions 3.6 through 7.0).
484
542
 
485
543
  ## Rust Crate Architecture 🦀
486
544
 
487
- The Rust engine is organized as a Cargo workspace with 8 focused crates:
545
+ The Rust engine is organized as a Cargo workspace with 9 focused crates:
488
546
 
489
547
  | Crate | Purpose |
490
548
  |---|---|
@@ -495,6 +553,7 @@ The Rust engine is organized as a Cargo workspace with 8 focused crates:
495
553
  | `rustdb-storage` | Storage backends (memory, file), OpLog with point-in-time replay |
496
554
  | `rustdb-index` | B-tree/hash indexes, query planner (IXSCAN/COLLSCAN) |
497
555
  | `rustdb-txn` | Transaction + session management with snapshot isolation |
556
+ | `rustdb-auth` | SCRAM-SHA-256 credential handling, user metadata persistence, RBAC checks |
498
557
  | `rustdb-commands` | 40+ command handlers wiring everything together |
499
558
 
500
559
  Cross-compiled for `linux_amd64` and `linux_arm64` via [@git.zone/tsrust](https://www.npmjs.com/package/@git.zone/tsrust).
@@ -507,6 +566,7 @@ The Bitcask-style file storage engine includes several reliability features:
507
566
  - **CRC32 checksums** — every record is integrity-checked on read
508
567
  - **Automatic compaction** — dead records are reclaimed when they exceed 50% of file size, runs on startup and after every write
509
568
  - **Hint file staleness detection** — the hint file records the data file size at write time; if data.rdb changed since (e.g. crash after a delete), the engine falls back to a full scan to ensure tombstones are not lost
569
+ - **Torn-tail repair** — startup scans `data.rdb` to the last valid record, truncates invalid trailing bytes, and preserves all verified records after interrupted writes
510
570
  - **Stale socket cleanup** — orphaned `/tmp/smartdb-*.sock` files from crashed instances are automatically cleaned up on startup
511
571
 
512
572
  ### Data Integrity CLI 🔍
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartdb',
6
- version: '2.7.0',
6
+ version: '2.8.0',
7
7
  description: 'A MongoDB-compatible embedded database server with wire protocol support, backed by a high-performance Rust engine.'
8
8
  }
@@ -2,7 +2,12 @@
2
2
 
3
3
  // Export server (the main entry point for using SmartDB)
4
4
  export { SmartdbServer } from './server/SmartdbServer.js';
5
- export type { ISmartdbServerOptions } from './server/SmartdbServer.js';
5
+ export type {
6
+ ISmartdbAuthOptions,
7
+ ISmartdbAuthUser,
8
+ ISmartdbServerOptions,
9
+ ISmartdbTlsOptions,
10
+ } from './server/SmartdbServer.js';
6
11
 
7
12
  // Export bridge for advanced usage
8
13
  export { RustDbBridge } from './rust-db-bridge.js';
@@ -76,6 +76,10 @@ export interface ISmartDbMetrics {
76
76
  collections: number;
77
77
  oplogEntries: number;
78
78
  oplogCurrentSeq: number;
79
+ sessions: number;
80
+ activeTransactions: number;
81
+ authEnabled: boolean;
82
+ authUsers: number;
79
83
  uptimeSeconds: number;
80
84
  }
81
85
 
@@ -117,6 +121,24 @@ interface ISmartDbRustConfig {
117
121
  storagePath?: string;
118
122
  persistPath?: string;
119
123
  persistIntervalMs?: number;
124
+ auth?: {
125
+ enabled?: boolean;
126
+ users?: Array<{
127
+ username: string;
128
+ password: string;
129
+ database?: string;
130
+ roles?: string[];
131
+ }>;
132
+ usersPath?: string;
133
+ scramIterations?: number;
134
+ };
135
+ tls?: {
136
+ enabled?: boolean;
137
+ certPath?: string;
138
+ keyPath?: string;
139
+ caPath?: string;
140
+ requireClientCert?: boolean;
141
+ };
120
142
  }
121
143
 
122
144
  /**
@@ -28,6 +28,32 @@ export interface ISmartdbServerOptions {
28
28
  persistPath?: string;
29
29
  /** Persistence interval in ms (default: 60000) */
30
30
  persistIntervalMs?: number;
31
+ /** Authentication configuration. Disabled by default. */
32
+ auth?: ISmartdbAuthOptions;
33
+ /** TLS transport configuration for TCP listeners. Disabled by default. */
34
+ tls?: ISmartdbTlsOptions;
35
+ }
36
+
37
+ export interface ISmartdbAuthOptions {
38
+ enabled?: boolean;
39
+ users?: ISmartdbAuthUser[];
40
+ usersPath?: string;
41
+ scramIterations?: number;
42
+ }
43
+
44
+ export interface ISmartdbAuthUser {
45
+ username: string;
46
+ password: string;
47
+ database?: string;
48
+ roles?: string[];
49
+ }
50
+
51
+ export interface ISmartdbTlsOptions {
52
+ enabled?: boolean;
53
+ certPath?: string;
54
+ keyPath?: string;
55
+ caPath?: string;
56
+ requireClientCert?: boolean;
31
57
  }
32
58
 
33
59
  /**
@@ -64,6 +90,8 @@ export class SmartdbServer {
64
90
  storagePath: options.storagePath ?? './data',
65
91
  persistPath: options.persistPath,
66
92
  persistIntervalMs: options.persistIntervalMs ?? 60000,
93
+ auth: options.auth,
94
+ tls: options.tls,
67
95
  };
68
96
  this.bridge = new RustDbBridge();
69
97
  }
@@ -106,6 +134,8 @@ export class SmartdbServer {
106
134
  storagePath: this.options.storagePath,
107
135
  persistPath: this.options.persistPath,
108
136
  persistIntervalMs: this.options.persistIntervalMs,
137
+ auth: this.options.auth,
138
+ tls: this.options.tls,
109
139
  });
110
140
 
111
141
  this.resolvedConnectionUri = result.connectionUri;
@@ -142,7 +172,8 @@ export class SmartdbServer {
142
172
  const encodedPath = encodeURIComponent(this.options.socketPath);
143
173
  return `mongodb://${encodedPath}`;
144
174
  }
145
- return `mongodb://${this.options.host ?? '127.0.0.1'}:${this.options.port ?? 27017}`;
175
+ const baseUri = `mongodb://${this.options.host ?? '127.0.0.1'}:${this.options.port ?? 27017}`;
176
+ return this.options.tls?.enabled ? `${baseUri}/?tls=true` : baseUri;
146
177
  }
147
178
 
148
179
  /**