wolfronix-sdk 2.4.1 → 2.4.2

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
@@ -1,117 +1,296 @@
1
1
  # wolfronix-sdk
2
2
 
3
- Official JavaScript/TypeScript SDK for Wolfronix - Zero-knowledge encryption made simple.
3
+ Official JavaScript/TypeScript SDK for **Wolfronix** Zero-knowledge encryption made simple.
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/wolfronix-sdk.svg)](https://www.npmjs.com/package/wolfronix-sdk)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
8
  ## Features
9
9
 
10
- - 🔐 **Zero-Knowledge Encryption** - Keys generated client-side, never leave your device
11
- - 🏢 **Enterprise Ready** - Seamless integration with your existing storage
12
- - 🚀 **Simple API** - Encrypt files in 2 lines of code
13
- - 📦 **TypeScript Native** - Full type definitions included
14
- - 🌐 **Universal** - Works in Node.js 18+ and modern browsers
15
- - 🔄 **Auto Retry** - Built-in retry logic with exponential backoff
10
+ - 🔐 **Zero-Knowledge Encryption** Keys generated client-side, never leave your device
11
+ - 🏢 **Enterprise Ready** Seamless integration with your existing storage (Supabase, MongoDB, MySQL, Firebase, PostgreSQL)
12
+ - 🚀 **Simple API** Encrypt files in 2 lines of code
13
+ - 📦 **TypeScript Native** Full type definitions included
14
+ - 🌐 **Universal** Works in Node.js 18+ and modern browsers
15
+ - 🔄 **Auto Retry** Built-in retry logic with exponential backoff
16
+ - 💬 **E2E Chat** — Hybrid RSA+AES message encryption out of the box
17
+ - 📡 **Real-Time Streaming** — WebSocket-based streaming encryption/decryption
16
18
 
17
- ## Backend Integration (Enterprise Mode)
19
+ ---
18
20
 
19
- To use this SDK, your backend API must implement 3 storage endpoints that Wolfronix will call:
21
+ ## Installation
20
22
 
21
- 1. **POST** `/wolfronix/files/upload` - Store encrypted file + metadata
22
- 2. **GET** `/wolfronix/files/{id}` - Retrieve metadata
23
- 3. **GET** `/wolfronix/files/{id}/data` - Retrieve encrypted file blob
23
+ ### npm / yarn / pnpm
24
24
 
25
- Wolfronix handles all encryption/decryption keys and logic; you only handle the encrypted blobs.
25
+ ```bash
26
+ npm install wolfronix-sdk
27
+ ```
26
28
 
29
+ ### Browser (Script Tag)
27
30
 
28
- ## Installation
31
+ For plain HTML/JS apps, use the pre-built browser bundle:
29
32
 
30
- ```bash
31
- npm install wolfronix-sdk
32
- # or
33
- yarn add wolfronix-sdk
34
- # or
35
- pnpm add wolfronix-sdk
33
+ ```html
34
+ <script src="https://unpkg.com/wolfronix-sdk/dist/index.global.js"></script>
35
+ <script>
36
+ // All exports are available on the global `Wolfronix` object
37
+ const wfx = new Wolfronix.default({
38
+ baseUrl: 'https://your-server:9443',
39
+ clientId: 'your-client-id',
40
+ wolfronixKey: 'your-api-key'
41
+ });
42
+ </script>
36
43
  ```
37
44
 
45
+ Or host the bundle yourself — copy `node_modules/wolfronix-sdk/dist/index.global.js` to your project.
46
+
47
+ ---
48
+
38
49
  ## Quick Start
39
50
 
40
- ```typescript
51
+ ### 1. Connect to Wolfronix Server
52
+
53
+ ```javascript
41
54
  import Wolfronix from 'wolfronix-sdk';
42
55
 
43
- // Initialize client
44
56
  const wfx = new Wolfronix({
45
- baseUrl: 'https://your-wolfronix-server:5002',
46
- clientId: 'your-enterprise-client-id',
47
- wolfronixKey: 'your-api-key'
57
+ baseUrl: 'https://your-wolfronix-server:9443',
58
+ clientId: 'your-client-id', // From enterprise registration
59
+ wolfronixKey: 'your-api-key', // From enterprise registration
48
60
  });
61
+ ```
49
62
 
50
- // Register (First time only) - Generates keys client-side
51
- await wfx.register('user@example.com', 'password123');
63
+ ### 2. Register a User (First Time Only)
64
+
65
+ ```javascript
66
+ await wfx.register('user@example.com', 'securePassword');
67
+ // Generates RSA key pair client-side, wraps private key with password,
68
+ // sends only the ENCRYPTED key to the server (zero-knowledge)
69
+ ```
52
70
 
53
- // Login (Subsequent visits)
54
- await wfx.login('user@example.com', 'password123');
71
+ ### 3. Login (Subsequent Visits)
55
72
 
56
- // Encrypt a file
57
- const result = await wfx.encrypt(file);
73
+ ```javascript
74
+ await wfx.login('user@example.com', 'securePassword');
75
+ // Fetches encrypted private key from server, decrypts it locally
76
+ ```
77
+
78
+ ### 4. Encrypt a File
79
+
80
+ ```javascript
81
+ const result = await wfx.encrypt(file); // File or Blob
58
82
  console.log('Encrypted! File ID:', result.file_id);
83
+ console.log('Time:', result.enc_time_ms, 'ms');
84
+ ```
59
85
 
60
- // Decrypt a file
61
- const decrypted = await wfx.decrypt(result.file_id);
86
+ ### 5. Decrypt a File
87
+
88
+ ```javascript
89
+ const blob = await wfx.decrypt(result.file_id);
90
+ // blob is a standard Blob — display, download, or process it
62
91
  ```
63
92
 
64
- ## Usage Examples
93
+ ### 6. List & Delete Files
94
+
95
+ ```javascript
96
+ const { files } = await wfx.listFiles();
97
+ await wfx.deleteFile(files[0].file_id);
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Step-by-Step Integration Guide
103
+
104
+ ### Plain HTML/JS Web App
105
+
106
+ ```html
107
+ <!DOCTYPE html>
108
+ <html>
109
+ <head>
110
+ <title>My Secure App</title>
111
+ <script src="https://unpkg.com/wolfronix-sdk/dist/index.global.js"></script>
112
+ </head>
113
+ <body>
114
+ <input type="email" id="email" placeholder="Email">
115
+ <input type="password" id="password" placeholder="Password">
116
+ <button onclick="doLogin()">Login</button>
117
+ <button onclick="doRegister()">Register</button>
118
+
119
+ <hr>
120
+
121
+ <input type="file" id="fileInput">
122
+ <button onclick="doEncrypt()">Encrypt & Upload</button>
123
+ <button onclick="doList()">List Files</button>
124
+
125
+ <div id="output"></div>
126
+
127
+ <script>
128
+ const wfx = new Wolfronix.default({
129
+ baseUrl: 'https://your-server:9443',
130
+ clientId: 'your-client-id',
131
+ wolfronixKey: 'your-api-key'
132
+ });
133
+
134
+ async function doRegister() {
135
+ const email = document.getElementById('email').value;
136
+ const pass = document.getElementById('password').value;
137
+ await wfx.register(email, pass);
138
+ alert('Registered! Keys generated.');
139
+ }
140
+
141
+ async function doLogin() {
142
+ const email = document.getElementById('email').value;
143
+ const pass = document.getElementById('password').value;
144
+ await wfx.login(email, pass);
145
+ alert('Logged in! User: ' + wfx.getUserId());
146
+ }
147
+
148
+ async function doEncrypt() {
149
+ const file = document.getElementById('fileInput').files[0];
150
+ const result = await wfx.encrypt(file);
151
+ document.getElementById('output').textContent =
152
+ 'Encrypted! ID: ' + result.file_id + ' (' + result.enc_time_ms + 'ms)';
153
+ }
154
+
155
+ async function doList() {
156
+ const { files } = await wfx.listFiles();
157
+ document.getElementById('output').textContent =
158
+ files.map(f => f.original_name + ' (ID: ' + f.file_id + ')').join('\n');
159
+ }
160
+ </script>
161
+ </body>
162
+ </html>
163
+ ```
65
164
 
66
- ### Browser (React, Vue, Angular, etc.)
165
+ ### React / Next.js
67
166
 
68
167
  ```typescript
69
168
  import Wolfronix from 'wolfronix-sdk';
70
169
 
71
- const wfx = new Wolfronix('https://wolfronix-server:5002');
170
+ // Create a singleton instance (e.g., in a context or module)
171
+ const wfx = new Wolfronix({
172
+ baseUrl: process.env.NEXT_PUBLIC_WOLFRONIX_URL!,
173
+ clientId: process.env.NEXT_PUBLIC_WOLFRONIX_CLIENT_ID!,
174
+ wolfronixKey: process.env.NEXT_PUBLIC_WOLFRONIX_KEY!,
175
+ });
72
176
 
73
- // With file input
74
- const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
75
- const file = event.target.files?.[0];
76
- if (!file) return;
177
+ export default function FileVault() {
178
+ const [files, setFiles] = useState([]);
77
179
 
78
- try {
79
- const { file_id } = await wfx.encrypt(file);
80
- console.log('File encrypted with your private key:', file_id);
81
- } catch (error) {
82
- console.error('Encryption failed:', error);
83
- }
84
- };
85
-
86
- // Download decrypted file
87
- const handleDownload = async (fileId: string, filename: string) => {
88
- const blob = await wfx.decrypt(fileId);
89
-
90
- // Create download link
91
- const url = URL.createObjectURL(blob);
92
- const a = document.createElement('a');
93
- a.href = url;
94
- a.download = filename;
95
- a.click();
96
- URL.revokeObjectURL(url);
97
- };
180
+ const handleLogin = async (email: string, password: string) => {
181
+ await wfx.login(email, password);
182
+ const { files } = await wfx.listFiles();
183
+ setFiles(files);
184
+ };
185
+
186
+ const handleUpload = async (file: File) => {
187
+ const result = await wfx.encrypt(file);
188
+ console.log('Encrypted:', result.file_id);
189
+ // Refresh file list
190
+ const { files } = await wfx.listFiles();
191
+ setFiles(files);
192
+ };
193
+
194
+ const handleDownload = async (fileId: string, filename: string) => {
195
+ const blob = await wfx.decrypt(fileId);
196
+ const url = URL.createObjectURL(blob);
197
+ const a = document.createElement('a');
198
+ a.href = url;
199
+ a.download = filename;
200
+ a.click();
201
+ URL.revokeObjectURL(url);
202
+ };
203
+
204
+ return (
205
+ <div>
206
+ <input type="file" onChange={(e) => handleUpload(e.target.files![0])} />
207
+ {files.map(f => (
208
+ <div key={f.file_id}>
209
+ {f.original_name}
210
+ <button onClick={() => handleDownload(f.file_id, f.original_name)}>
211
+ Download
212
+ </button>
213
+ </div>
214
+ ))}
215
+ </div>
216
+ );
217
+ }
98
218
  ```
99
219
 
100
- ### Node.js
220
+ ### React Hook
221
+
222
+ ```typescript
223
+ // hooks/useWolfronix.ts
224
+ import { useState, useCallback, useMemo } from 'react';
225
+ import Wolfronix, { FileInfo } from 'wolfronix-sdk';
226
+
227
+ export function useWolfronix(baseUrl: string, clientId?: string, wolfronixKey?: string) {
228
+ const [isLoading, setIsLoading] = useState(false);
229
+ const [error, setError] = useState<Error | null>(null);
230
+ const [files, setFiles] = useState<FileInfo[]>([]);
231
+
232
+ const client = useMemo(
233
+ () => new Wolfronix({ baseUrl, clientId, wolfronixKey }),
234
+ [baseUrl, clientId, wolfronixKey]
235
+ );
236
+
237
+ const login = useCallback(async (email: string, password: string) => {
238
+ setIsLoading(true);
239
+ try {
240
+ return await client.login(email, password);
241
+ } catch (e) {
242
+ setError(e as Error);
243
+ throw e;
244
+ } finally {
245
+ setIsLoading(false);
246
+ }
247
+ }, [client]);
248
+
249
+ const encrypt = useCallback(async (file: File) => {
250
+ setIsLoading(true);
251
+ try {
252
+ const result = await client.encrypt(file);
253
+ const { files } = await client.listFiles();
254
+ setFiles(files);
255
+ return result;
256
+ } catch (e) {
257
+ setError(e as Error);
258
+ throw e;
259
+ } finally {
260
+ setIsLoading(false);
261
+ }
262
+ }, [client]);
263
+
264
+ const decrypt = useCallback(async (fileId: string) => {
265
+ setIsLoading(true);
266
+ try {
267
+ return await client.decrypt(fileId);
268
+ } catch (e) {
269
+ setError(e as Error);
270
+ throw e;
271
+ } finally {
272
+ setIsLoading(false);
273
+ }
274
+ }, [client]);
275
+
276
+ return { client, isLoading, error, files, login, encrypt, decrypt };
277
+ }
278
+ ```
279
+
280
+ ### Node.js (Server-Side)
101
281
 
102
282
  ```typescript
103
283
  import Wolfronix from 'wolfronix-sdk';
104
284
  import * as fs from 'fs';
105
285
 
106
286
  const wfx = new Wolfronix({
107
- baseUrl: 'https://wolfronix-server:5002',
287
+ baseUrl: 'https://wolfronix-server:9443',
108
288
  clientId: 'your-client-id',
109
289
  wolfronixKey: 'your-api-key',
110
- insecure: true // For self-signed certs in development
290
+ insecure: true // For self-signed certs in development
111
291
  });
112
292
 
113
293
  async function main() {
114
- // Login
115
294
  await wfx.login('user@example.com', 'password123');
116
295
 
117
296
  // Encrypt a file
@@ -131,291 +310,364 @@ async function main() {
131
310
  main();
132
311
  ```
133
312
 
134
- ### 💬 E2E Encrypted Chat Integration
313
+ ---
135
314
 
136
- Turn any chat app into a secure, end-to-end encrypted messenger in minutes.
315
+ ## API Reference
316
+
317
+ ### Constructor
318
+
319
+ ```typescript
320
+ new Wolfronix(config: WolfronixConfig | string)
321
+ ```
322
+
323
+ | Option | Type | Default | Description |
324
+ |--------|------|---------|-------------|
325
+ | `baseUrl` | `string` | **required** | Wolfronix server URL |
326
+ | `clientId` | `string` | `''` | Enterprise client ID |
327
+ | `wolfronixKey` | `string` | `''` | API key (sent as `X-Wolfronix-Key` header) |
328
+ | `timeout` | `number` | `30000` | Request timeout in ms (file uploads bypass this) |
329
+ | `retries` | `number` | `3` | Max retry attempts with exponential backoff |
330
+ | `insecure` | `boolean` | `false` | Skip SSL verification (Node.js only) |
331
+
332
+ You can also pass just a URL string: `new Wolfronix('https://server:9443')`
333
+
334
+ ---
335
+
336
+ ### Authentication
337
+
338
+ | Method | Returns | Description |
339
+ |--------|---------|-------------|
340
+ | `register(email, password)` | `Promise<AuthResponse>` | Generate RSA keys + register (first time) |
341
+ | `login(email, password)` | `Promise<AuthResponse>` | Fetch & unwrap keys (subsequent logins) |
342
+ | `setToken(token, userId?)` | `void` | Set auth token directly (for custom auth) |
343
+ | `logout()` | `void` | Clear keys and session from memory |
344
+ | `isAuthenticated()` | `boolean` | Check if user is logged in |
345
+ | `getUserId()` | `string \| null` | Get current user ID |
346
+ | `hasPrivateKey()` | `boolean` | Check if RSA private key is loaded in memory |
347
+
348
+ ---
349
+
350
+ ### File Operations
351
+
352
+ | Method | Returns | Description |
353
+ |--------|---------|-------------|
354
+ | `encrypt(file, filename?)` | `Promise<EncryptResponse>` | Encrypt and store a file |
355
+ | `decrypt(fileId, role?)` | `Promise<Blob>` | Decrypt file → Blob (for browser display/download) |
356
+ | `decryptToBuffer(fileId, role?)` | `Promise<ArrayBuffer>` | Decrypt file → ArrayBuffer (for Node.js) |
357
+ | `getFileKey(fileId)` | `Promise<KeyPartResponse>` | Get encrypted key_part_a (advanced use) |
358
+ | `listFiles()` | `Promise<ListFilesResponse>` | List user's encrypted files |
359
+ | `deleteFile(fileId)` | `Promise<DeleteResponse>` | Delete an encrypted file |
360
+
361
+ **`EncryptResponse` fields:**
362
+ ```typescript
363
+ {
364
+ status: string;
365
+ file_id: string;
366
+ file_size: number;
367
+ enc_time_ms: number;
368
+ // Detailed timing breakdown:
369
+ upload_ms?: number; // Network upload time
370
+ read_ms?: number; // Server file read time
371
+ encrypt_ms?: number; // AES-256-GCM encryption time
372
+ store_ms?: number; // Storage write time
373
+ }
374
+ ```
375
+
376
+ ---
377
+
378
+ ### E2E Chat Encryption
379
+
380
+ Turn any chat app into a secure, end-to-end encrypted messenger.
381
+
382
+ | Method | Returns | Description |
383
+ |--------|---------|-------------|
384
+ | `getPublicKey(userId, clientId?)` | `Promise<CryptoKey>` | Fetch a user's RSA public key |
385
+ | `encryptMessage(text, recipientId)` | `Promise<string>` | Encrypt text for a recipient (returns JSON packet) |
386
+ | `decryptMessage(packetString)` | `Promise<string>` | Decrypt a received message packet |
137
387
 
138
388
  **Sender (Alice):**
139
389
  ```typescript
140
- // 1. Get Bob's Public Key & Encrypt Message
141
- const securePacket = await wfx.encryptMessage("Secret details at 5 PM", "bob_user_id");
390
+ const securePacket = await wfx.encryptMessage("Secret meeting at 5 PM", "bob_user_id");
142
391
 
143
- // 2. Send 'securePacket' string via your normal chat API (Socket.io, Firebase, etc.)
144
- chatSocket.emit('message', {
145
- to: 'bob',
146
- text: securePacket // Valid JSON string
147
- });
392
+ // Send via your regular chat backend (Socket.io, Firebase, etc.)
393
+ chatSocket.emit('message', { to: 'bob', text: securePacket });
148
394
  ```
149
395
 
150
396
  **Recipient (Bob):**
151
397
  ```typescript
152
- // 1. Receive message from chat server
153
398
  chatSocket.on('message', async (msg) => {
154
- try {
155
- // 2. Decrypt locally with Bob's Private Key
156
- const plainText = await wfx.decryptMessage(msg.text);
157
- console.log("Decrypted:", plainText);
158
- } catch (err) {
159
- console.error("Could not decrypt message");
160
- }
399
+ const plainText = await wfx.decryptMessage(msg.text);
400
+ console.log("Decrypted:", plainText);
161
401
  });
162
402
  ```
163
403
 
164
- **Features:**
165
- - **Hybrid Encryption:** Uses AES-256 for messages + RSA-2048 for key exchange (Fast & Secure).
166
- - **Zero-Knowledge:** Your chat server only sees encrypted packets.
167
- - **Universal:** Works with any backend (Socket.io, Firebase, PostgreSQL, etc).
404
+ ---
168
405
 
169
- ## API Reference
406
+ ### Server-Side Message Encryption
170
407
 
171
- ### Constructor
408
+ For messages that need **server-managed** encryption (Layer 3/4 dual-key split):
409
+
410
+ | Method | Returns | Description |
411
+ |--------|---------|-------------|
412
+ | `serverEncrypt(message, options?)` | `Promise<ServerEncryptResult>` | Encrypt a message server-side |
413
+ | `serverDecrypt(params)` | `Promise<string>` | Decrypt a server-encrypted message |
414
+ | `serverEncryptBatch(messages, options?)` | `Promise<ServerBatchEncryptResult>` | Batch encrypt multiple messages |
415
+ | `serverDecryptBatchItem(item)` | `Promise<string>` | Decrypt a single batch item |
172
416
 
173
417
  ```typescript
174
- new Wolfronix(config: WolfronixConfig | string)
418
+ // Encrypt
419
+ const encrypted = await wfx.serverEncrypt("Confidential data", { layer: 4 });
420
+
421
+ // Decrypt
422
+ const original = await wfx.serverDecrypt({
423
+ encryptedMessage: encrypted.encrypted_message,
424
+ nonce: encrypted.nonce,
425
+ keyPartA: encrypted.key_part_a,
426
+ messageTag: encrypted.message_tag
427
+ });
428
+
429
+ // Batch encrypt
430
+ const batch = await wfx.serverEncryptBatch([
431
+ { id: 'msg1', message: 'Hello' },
432
+ { id: 'msg2', message: 'World' }
433
+ ], { layer: 4 });
175
434
  ```
176
435
 
177
- | Option | Type | Default | Description |
178
- |--------|------|---------|-------------|
179
- | `baseUrl` | string | required | Wolfronix server URL |
180
- | `clientId` | string | `''` | Enterprise client ID |
181
- | `wolfronixKey` | string | `''` | API key for X-Wolfronix-Key auth |
182
- | `timeout` | number | `30000` | Request timeout (ms) |
183
- | `retries` | number | `3` | Max retry attempts |
184
- | `insecure` | boolean | `false` | Skip SSL verification (Node.js: uses undici Agent, or set `NODE_TLS_REJECT_UNAUTHORIZED=0`) |
436
+ ---
185
437
 
186
- ### Authentication
438
+ ### Real-Time Streaming Encryption
187
439
 
188
- | Method | Description |
189
- |--------|-------------|
190
- | `register(email, password)` | Register new user |
191
- | `login(email, password)` | Login existing user |
192
- | `setToken(token, userId?)` | Set auth token directly |
193
- | `logout()` | Clear authentication |
194
- | `isAuthenticated()` | Check auth status |
195
- | `getUserId()` | Get current user ID |
440
+ For encrypting/decrypting live data streams (audio, video, real-time feeds) via WebSocket:
196
441
 
197
- ### File Operations
442
+ | Method | Returns | Description |
443
+ |--------|---------|-------------|
444
+ | `createStream(direction, streamKey?)` | `Promise<WolfronixStream>` | Open a streaming encryption session |
198
445
 
199
- | Method | Description |
200
- |--------|-------------|
201
- | `encrypt(file, filename?)` | Encrypt and store file |
202
- | `decrypt(fileId, role?)` | Decrypt file (zero-knowledge, returns Blob) |
203
- | `decryptToBuffer(fileId, role?)` | Decrypt file (zero-knowledge, returns ArrayBuffer) |
204
- | `getFileKey(fileId)` | Get encrypted key_part_a for client-side decryption |
205
- | `listFiles()` | List user's encrypted files |
206
- | `deleteFile(fileId)` | Delete encrypted file |
446
+ ```typescript
447
+ // Encrypt stream
448
+ const stream = await wfx.createStream('encrypt');
449
+ stream.onData((chunk, seq) => sendToRecipient(chunk));
450
+ stream.onError((err) => console.error(err));
207
451
 
208
- ### E2E Chat Encryption
452
+ const processed = await stream.send('data to encrypt'); // Text
453
+ const processed2 = await stream.sendBinary(audioChunk); // Binary
209
454
 
210
- | Method | Description |
211
- |--------|-------------|
212
- | `getPublicKey(userId, clientId?)` | Fetch a user's RSA public key |
213
- | `encryptMessage(text, recipientId)` | Encrypt text for a recipient (returns packet string) |
214
- | `decryptMessage(packetString)` | Decrypt a received message packet |
455
+ // Save these for the recipient to decrypt:
456
+ console.log('Key:', stream.keyPartA, 'Tag:', stream.streamTag);
215
457
 
216
- ### Utility
458
+ const summary = await stream.end();
459
+ console.log('Chunks processed:', summary.chunksProcessed);
217
460
 
218
- | Method | Description |
219
- |--------|-------------|
220
- | `getMetrics()` | Get encryption/decryption stats |
221
- | `healthCheck()` | Check server availability |
461
+ // Decrypt stream (recipient)
462
+ const decStream = await wfx.createStream('decrypt', {
463
+ keyPartA: senderKeyPartA,
464
+ streamTag: senderStreamTag
465
+ });
466
+ decStream.onData((chunk, seq) => playAudio(chunk));
467
+ ```
222
468
 
223
- ## Security Architecture (v2.0)
469
+ ---
224
470
 
225
- ### Zero-Knowledge Decryption Flow
471
+ ### Admin API (Enterprise Client Management)
226
472
 
227
- In v2.0, the private key **never leaves the client**. The decrypt flow works as follows:
473
+ For managing enterprise clients programmatically:
228
474
 
475
+ ```typescript
476
+ import { WolfronixAdmin } from 'wolfronix-sdk';
477
+
478
+ const admin = new WolfronixAdmin({
479
+ baseUrl: 'https://your-server:9443',
480
+ adminKey: 'your-admin-api-key'
481
+ });
229
482
  ```
230
- Client Wolfronix Server
231
- │ │
232
- │ GET /files/{id}/key │
233
- │──────────────────────────────────────>│
234
- │ { key_part_a: "<RSA-OAEP encrypted>"}│
235
- │<──────────────────────────────────────│
236
- │ │
237
- │ [Decrypt key_part_a locally │
238
- │ with private key (RSA-OAEP)] │
239
- │ │
240
- │ POST /files/{id}/decrypt │
241
- │ { decrypted_key_a: "<base64>" } │
242
- │──────────────────────────────────────>│
243
- │ │
244
- │ [Server combines key_a + key_b,
245
- │ decrypts with AES-256-GCM] │
246
- │ │
247
- │ <decrypted file bytes> │
248
- │<──────────────────────────────────────│
483
+
484
+ | Method | Returns | Description |
485
+ |--------|---------|-------------|
486
+ | `registerClient(params)` | `Promise<RegisterClientResponse>` | Register a new enterprise client |
487
+ | `listClients()` | `Promise<ListClientsResponse>` | List all registered clients |
488
+ | `getClient(clientId)` | `Promise<EnterpriseClient>` | Get details for a specific client |
489
+ | `updateClient(clientId, params)` | `Promise<UpdateClientResponse>` | Update client configuration |
490
+ | `deactivateClient(clientId)` | `Promise<DeactivateClientResponse>` | Deactivate (revoke) a client |
491
+ | `healthCheck()` | `Promise<boolean>` | Check server health |
492
+
493
+ ```typescript
494
+ // Register a new client with Supabase connector
495
+ const result = await admin.registerClient({
496
+ client_id: 'acme_corp',
497
+ client_name: 'Acme Corporation',
498
+ db_type: 'supabase', // or: mongodb, mysql, firebase, postgresql, custom_api
499
+ db_config: JSON.stringify({
500
+ supabase_url: 'https://xxx.supabase.co',
501
+ supabase_service_key: 'eyJ...'
502
+ })
503
+ });
504
+
505
+ console.log('Wolfronix Key:', result.wolfronix_key); // Give this to the client
249
506
  ```
250
507
 
251
- ### Key Security Properties
252
- - **AES-256-GCM** authenticated encryption (tamper-proof, replaces AES-CTR)
253
- - **RSA-OAEP** with SHA-256 for key transport (replaces PKCS1v15)
254
- - **API key authentication** via `X-Wolfronix-Key` header on all endpoints
255
- - **Configurable CORS** origins (no more wildcard `*`)
256
- - **Dual-key split**: AES key split in half, each half encrypted with different RSA key
257
- - **Zero-knowledge key wrapping**: Private keys wrapped with PBKDF2-derived keys, server never sees raw private keys
508
+ ---
509
+
510
+ ### Utility Methods
511
+
512
+ | Method | Returns | Description |
513
+ |--------|---------|-------------|
514
+ | `getMetrics()` | `Promise<MetricsResponse>` | Get encryption/decryption stats |
515
+ | `healthCheck()` | `Promise<boolean>` | Check if server is reachable |
516
+
517
+ ---
258
518
 
259
519
  ## Error Handling
260
520
 
261
- The SDK provides specific error types for different scenarios:
521
+ The SDK provides typed error classes for different failure scenarios:
262
522
 
263
523
  ```typescript
264
- import Wolfronix, {
265
- WolfronixError,
266
- AuthenticationError,
267
- FileNotFoundError,
268
- PermissionDeniedError,
269
- NetworkError,
270
- ValidationError
524
+ import Wolfronix, {
525
+ WolfronixError, // Base error class
526
+ AuthenticationError, // Invalid credentials or expired session
527
+ FileNotFoundError, // File doesn't exist
528
+ PermissionDeniedError, // Not authorized for this file
529
+ NetworkError, // Server unreachable
530
+ ValidationError // Invalid input parameters
271
531
  } from 'wolfronix-sdk';
272
532
 
273
533
  try {
274
534
  await wfx.encrypt(file);
275
535
  } catch (error) {
276
536
  if (error instanceof AuthenticationError) {
277
- // Token expired, redirect to login
278
- router.push('/login');
537
+ // Redirect to login
279
538
  } else if (error instanceof FileNotFoundError) {
280
- // File doesn't exist
281
- showToast('File not found');
282
- } else if (error instanceof PermissionDeniedError) {
283
- // Not your file
284
- showToast('Access denied');
539
+ // File was deleted
285
540
  } else if (error instanceof NetworkError) {
286
- // Server unreachable
287
- showToast('Connection failed. Retrying...');
541
+ // Server down — SDK already retried 3 times
288
542
  } else if (error instanceof ValidationError) {
289
- // Invalid input
290
- showToast(error.message);
291
- } else {
292
- // Unknown error
293
- console.error('Unexpected error:', error);
543
+ // Bad input (e.g., missing file, empty message)
294
544
  }
295
545
  }
296
546
  ```
297
547
 
298
- ## TypeScript Support
548
+ All errors include:
549
+ - `error.message` — Human-readable description
550
+ - `error.code` — Machine-readable error code
551
+ - `error.statusCode` — HTTP status code (if applicable)
552
+ - `error.details` — Server error details (if available)
299
553
 
300
- The SDK is written in TypeScript and includes full type definitions:
554
+ ---
301
555
 
302
- ```typescript
303
- import Wolfronix, {
304
- WolfronixConfig,
305
- AuthResponse,
306
- EncryptResponse,
307
- FileInfo,
308
- ListFilesResponse,
309
- MetricsResponse
310
- } from 'wolfronix-sdk';
556
+ ## Security Architecture
311
557
 
312
- // All methods are fully typed
313
- const config: WolfronixConfig = {
314
- baseUrl: 'https://server:5002',
315
- clientId: 'my-client',
316
- wolfronixKey: 'my-api-key'
317
- };
558
+ ### How It Works
318
559
 
319
- const wfx = new Wolfronix(config);
320
- const response: EncryptResponse = await wfx.encrypt(file);
560
+ ```
561
+ Your App Wolfronix Engine
562
+ ┌──────────────┐ ┌────────────────────────┐
563
+ User ──────▶ │ SDK (Browser)│ ──────────▶ │ AES-256-GCM Encrypt │
564
+ Password │ │ HTTPS │ RSA Dual-Key Split │
565
+ │ RSA Keys │ │ RBAC Masking │
566
+ │ (client- │ ◀────────── │ │
567
+ │ side only) │ Encrypted │ Stores NOTHING │
568
+ └──────────────┘ Blob Only │ decryptable alone │
569
+ └────────────────────────┘
570
+
571
+
572
+ ┌────────────────────────┐
573
+ │ Your Database │
574
+ │ (Supabase, MongoDB, │
575
+ │ PostgreSQL, etc.) │
576
+ │ Stores encrypted │
577
+ │ blobs only │
578
+ └────────────────────────┘
321
579
  ```
322
580
 
323
- ## React Hook Example
324
-
325
- ```typescript
326
- // useWolfronix.ts
327
- import { useState, useCallback, useMemo } from 'react';
328
- import Wolfronix, { FileInfo as WolfronixFile } from 'wolfronix-sdk';
329
-
330
- export function useWolfronix(baseUrl: string, clientId?: string, wolfronixKey?: string) {
331
- const [isLoading, setIsLoading] = useState(false);
332
- const [error, setError] = useState<Error | null>(null);
333
- const [files, setFiles] = useState<WolfronixFile[]>([]);
581
+ ### Key Security Properties
334
582
 
335
- const client = useMemo(() => new Wolfronix({ baseUrl, clientId, wolfronixKey }), [baseUrl, clientId, wolfronixKey]);
583
+ | Property | Implementation |
584
+ |----------|---------------|
585
+ | **Encryption** | AES-256-GCM (authenticated, tamper-proof) |
586
+ | **Key Transport** | RSA-OAEP with SHA-256 |
587
+ | **Key Wrapping** | PBKDF2 (100,000 iterations) + AES-GCM |
588
+ | **Dual-Key Split** | AES key split in half; each half encrypted with different RSA key |
589
+ | **Zero-Knowledge** | Private keys wrapped client-side; server never sees raw keys |
590
+ | **Auth** | API key (`X-Wolfronix-Key`) + zero-knowledge login |
336
591
 
337
- const login = useCallback(async (email: string, password: string) => {
338
- setIsLoading(true);
339
- setError(null);
340
- try {
341
- return await client.login(email, password);
342
- } catch (e) {
343
- setError(e as Error);
344
- throw e;
345
- } finally {
346
- setIsLoading(false);
347
- }
348
- }, [client]);
592
+ ### Zero-Knowledge Decryption Flow
349
593
 
350
- const encrypt = useCallback(async (file: File) => {
351
- setIsLoading(true);
352
- setError(null);
353
- try {
354
- const result = await client.encrypt(file);
355
- await refreshFiles();
356
- return result;
357
- } catch (e) {
358
- setError(e as Error);
359
- throw e;
360
- } finally {
361
- setIsLoading(false);
362
- }
363
- }, [client]);
594
+ ```
595
+ Client Wolfronix Server
596
+ │ │
597
+ │ GET /files/{id}/key │
598
+ │──────────────────────────────────────►│
599
+ │ { key_part_a: "<RSA-OAEP encrypted>"}│
600
+ │◄──────────────────────────────────────│
601
+ │ │
602
+ │ [Decrypt key_part_a locally │
603
+ │ with private key (RSA-OAEP)] │
604
+ │ │
605
+ │ POST /files/{id}/decrypt │
606
+ │ { decrypted_key_a: "<base64>" }
607
+ │──────────────────────────────────────►│
608
+ │ │
609
+ │ [Server combines key_a + key_b, │
610
+ │ decrypts with AES-256-GCM] │
611
+ │ │
612
+ │ <decrypted file bytes> │
613
+ │◄──────────────────────────────────────│
614
+ ```
364
615
 
365
- const decrypt = useCallback(async (fileId: string) => {
366
- setIsLoading(true);
367
- setError(null);
368
- try {
369
- return await client.decrypt(fileId);
370
- } catch (e) {
371
- setError(e as Error);
372
- throw e;
373
- } finally {
374
- setIsLoading(false);
375
- }
376
- }, [client]);
616
+ ---
377
617
 
378
- const refreshFiles = useCallback(async () => {
379
- const { files } = await client.listFiles();
380
- setFiles(files);
381
- }, [client]);
618
+ ## TypeScript Types
382
619
 
383
- return {
384
- client,
385
- isLoading,
386
- error,
387
- files,
388
- login,
389
- encrypt,
390
- decrypt,
391
- refreshFiles
392
- };
393
- }
620
+ All interfaces are exported for full type safety:
394
621
 
395
- // Usage in component
396
- function FileManager() {
397
- const { files, encrypt, decrypt, isLoading } = useWolfronix(
398
- 'https://wolfronix:5002',
399
- 'my-client-id'
400
- );
622
+ ```typescript
623
+ import Wolfronix, {
624
+ // Config
625
+ WolfronixConfig,
626
+ WolfronixAdminConfig,
401
627
 
402
- return (
403
- <div>
404
- <input type="file" onChange={(e) => encrypt(e.target.files![0])} />
405
- {isLoading && <Spinner />}
406
- {files.map(f => (
407
- <div key={f.file_id} onClick={() => decrypt(f.file_id)}>
408
- {f.original_name}
409
- </div>
410
- ))}
411
- </div>
412
- );
413
- }
628
+ // Responses
629
+ AuthResponse,
630
+ EncryptResponse,
631
+ FileInfo,
632
+ ListFilesResponse,
633
+ DeleteResponse,
634
+ KeyPartResponse,
635
+ MetricsResponse,
636
+
637
+ // Message Encryption
638
+ EncryptMessagePacket,
639
+ ServerEncryptResult,
640
+ ServerDecryptParams,
641
+ ServerBatchEncryptResult,
642
+
643
+ // Streaming
644
+ WolfronixStream,
645
+ StreamSession,
646
+ StreamChunk,
647
+
648
+ // Enterprise Admin
649
+ WolfronixAdmin,
650
+ RegisterClientRequest,
651
+ RegisterClientResponse,
652
+ EnterpriseClient,
653
+ ListClientsResponse,
654
+ UpdateClientRequest,
655
+ UpdateClientResponse,
656
+ DeactivateClientResponse,
657
+
658
+ // Error Classes
659
+ WolfronixError,
660
+ AuthenticationError,
661
+ FileNotFoundError,
662
+ PermissionDeniedError,
663
+ NetworkError,
664
+ ValidationError
665
+ } from 'wolfronix-sdk';
414
666
  ```
415
667
 
416
- ## Real-World Use Cases
668
+ ---
417
669
 
418
- Wolfronix can be integrated into **any application** that handles sensitive data:
670
+ ## Real-World Use Cases
419
671
 
420
672
  | Industry | Application | How Wolfronix Helps |
421
673
  |----------|------------|---------------------|
@@ -424,22 +676,51 @@ Wolfronix can be integrated into **any application** that handles sensitive data
424
676
  | ⚖️ **Legal** | Contracts, case files | Zero-knowledge confidential storage |
425
677
  | ☁️ **Cloud Storage** | Drive/Dropbox alternatives | Encrypted file vault with user-owned keys |
426
678
  | 🏢 **Enterprise** | HR records, internal docs | Per-employee encryption isolation |
679
+ | 💬 **Messaging** | Chat attachments | Encrypted file sharing + E2E messages |
427
680
  | 🎓 **Education** | Exam papers, student data | Tamper-proof academic records |
428
- | 💬 **Messaging** | File attachments | Encrypted file sharing in chat apps |
429
- | 🛒 **E-commerce** | Order docs, payment receipts | PCI-compliant document storage |
681
+
682
+ ---
683
+
684
+ ## Backend Integration
685
+
686
+ Your backend only needs to store/retrieve encrypted blobs. Wolfronix handles all crypto.
687
+
688
+ ### Supported Connectors (Managed)
689
+
690
+ | Connector | `db_type` | What You Provide |
691
+ |-----------|-----------|-----------------|
692
+ | Supabase | `supabase` | `supabase_url`, `supabase_service_key` |
693
+ | MongoDB | `mongodb` | `connection_string`, `database` |
694
+ | MySQL | `mysql` | `host`, `port`, `user`, `password`, `database` |
695
+ | Firebase | `firebase` | `project_id`, `service_account_key` |
696
+ | PostgreSQL | `postgresql` | `host`, `port`, `user`, `password`, `database` |
697
+ | Custom API | `custom_api` | Your own REST endpoint |
698
+
699
+ ### Custom API Mode
700
+
701
+ If using `custom_api`, your backend must implement these endpoints:
702
+
703
+ | Method | Endpoint | Purpose |
704
+ |--------|----------|---------|
705
+ | `POST` | `/wolfronix/files/upload` | Store encrypted file + metadata |
706
+ | `GET` | `/wolfronix/files/{id}` | Retrieve file metadata |
707
+ | `GET` | `/wolfronix/files/{id}/data` | Retrieve encrypted blob |
708
+ | `DELETE` | `/wolfronix/files/{id}` | Delete file |
709
+
710
+ ---
430
711
 
431
712
  ## Requirements
432
713
 
433
- - Node.js 18+ (for Node.js usage)
434
- - Modern browser with Web Crypto API support
714
+ - **Node.js:** 18+ (for server-side usage)
715
+ - **Browser:** Any modern browser with Web Crypto API (Chrome, Firefox, Safari, Edge)
716
+ - **Wolfronix Engine:** v2.4.1+
435
717
 
436
718
  ## License
437
719
 
438
- MIT License - see [LICENSE](./LICENSE) for details.
720
+ MIT License see [LICENSE](./LICENSE) for details.
439
721
 
440
722
  ## Links
441
723
 
442
- - [Documentation](https://wolfronix.com/docs)
443
- - [API Reference](https://wolfronix.com/docs/api)
724
+ - [npm Package](https://www.npmjs.com/package/wolfronix-sdk)
444
725
  - [GitHub](https://github.com/wolfronix/sdk-javascript)
445
726
  - [Report Issues](https://github.com/wolfronix/sdk-javascript/issues)
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@
3
3
  * Zero-knowledge encryption made simple
4
4
  *
5
5
  * @package @wolfronix/sdk
6
- * @version 2.4.0
6
+ * @version 2.4.2
7
7
  */
8
8
  interface WolfronixConfig {
9
9
  /** Wolfronix server base URL */
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * Zero-knowledge encryption made simple
4
4
  *
5
5
  * @package @wolfronix/sdk
6
- * @version 2.4.0
6
+ * @version 2.4.2
7
7
  */
8
8
  interface WolfronixConfig {
9
9
  /** Wolfronix server base URL */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolfronix-sdk",
3
- "version": "2.4.1",
3
+ "version": "2.4.2",
4
4
  "description": "Official Wolfronix SDK for JavaScript/TypeScript - Zero-knowledge encryption made simple",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",