aegis-lock 2.0.0 → 2.0.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
@@ -1,9 +1,17 @@
1
1
  # aegis-lock
2
2
 
3
- **Database-agnostic client-side AES-256-GCM field-level encryption.**
3
+ [![npm version](https://badge.fury.io/js/aegis-lock.svg)](https://badge.fury.io/js/aegis-lock)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ **Database-agnostic client-side AES-256-GCM field-level encryption with Contextual Binding and Blind Indexing.**
4
7
 
5
8
  Encrypt sensitive fields before they leave the browser or server. Decrypt after select. Zero plaintext hits the wire or your database. Works with **Supabase**, **MongoDB**, or any database via custom adapters.
6
9
 
10
+ > **⚠️ SECURITY WARNING:** `aegis-lock` provides the cryptographic primitives, but **you are responsible for your keys.** Never hardcode `CryptoKey` exports in your source code. Always use a secure Key Management Service (KMS) or strict, vault-backed environment variables to inject your keys at runtime.
11
+
12
+ ## Requirements
13
+ * Node.js 18+ (or any environment supporting the standard Web Crypto API, such as modern browsers, Cloudflare Workers, or Vercel Edge functions).
14
+
7
15
  ## Install
8
16
 
9
17
  ```bash
@@ -14,26 +22,41 @@ npm install aegis-lock
14
22
 
15
23
  ```typescript
16
24
  import { createClient } from "@supabase/supabase-js";
17
- import { AegisClient, SupabaseAdapter, generateKey, exportKey } from "aegis-lock";
25
+ import { AegisClient, SupabaseAdapter, generateKey, generateBidxKey, exportKey } from "aegis-lock";
18
26
 
19
27
  const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
20
28
  const adapter = new SupabaseAdapter(supabase);
21
29
 
30
+ // Generate your master encryption key and searchable blind index key
22
31
  const key = await generateKey();
23
- const exported = await exportKey(key); // save this securely!
24
-
25
- const aegis = new AegisClient(adapter, key, {
26
- secure_fields: ["encrypted_content", "ssn", "credit_card"],
27
- });
32
+ const bidxKey = await generateBidxKey();
33
+
34
+ // Export and save these securely! e.g., await exportKey(key)
35
+
36
+ const aegis = new AegisClient({
37
+ adapter,
38
+ primaryKeyField: "record_id", // REQUIRED: Binds ciphertext to the row to prevent tampering
39
+ encryptedFields: {
40
+ secure_fields: ["encrypted_content", "ssn", "email"]
41
+ },
42
+ bidxFields: {
43
+ secure_fields: ["email"] // Optional: Creates an 'email_bidx' column for searching
44
+ }
45
+ }, key, bidxKey);
28
46
 
29
- // Insert — fields are auto-encrypted
47
+ // Insert — fields are auto-encrypted.
48
+ // Note: You MUST provide the primary key application-side!
30
49
  await aegis.insert("secure_fields", {
31
- record_id: "some-uuid",
50
+ record_id: "uuid-1234-5678",
51
+ email: "alice@example.com",
32
52
  encrypted_content: "Top secret",
33
53
  });
34
54
 
35
- // Select — fields are auto-decrypted
36
- const { data } = await aegis.select("secure_fields");
55
+ // Select — Aegis automatically hashes the email to search the 'email_bidx' column securely
56
+ const { data } = await aegis.select("secure_fields", {
57
+ column: "email",
58
+ value: "alice@example.com"
59
+ });
37
60
  ```
38
61
 
39
62
  ## Quick Start — MongoDB
@@ -41,6 +64,7 @@ const { data } = await aegis.select("secure_fields");
41
64
  ```typescript
42
65
  import { MongoClient } from "mongodb";
43
66
  import { AegisClient, MongoDBAdapter, generateKey } from "aegis-lock";
67
+ import { v4 as uuidv4 } from "uuid";
44
68
 
45
69
  const mongo = new MongoClient("mongodb://localhost:27017");
46
70
  await mongo.connect();
@@ -48,11 +72,18 @@ const adapter = new MongoDBAdapter(mongo.db("myapp"));
48
72
 
49
73
  const key = await generateKey();
50
74
 
51
- const aegis = new AegisClient(adapter, key, {
52
- users: ["ssn", "credit_card"],
53
- });
75
+ const aegis = new AegisClient({
76
+ adapter,
77
+ primaryKeyField: "_id",
78
+ encryptedFields: {
79
+ users: ["ssn", "credit_card"]
80
+ }
81
+ }, key);
54
82
 
55
- await aegis.insert("users", { name: "Alice", ssn: "123-45-6789" });
83
+ // Insert with a client-generated ID
84
+ await aegis.insert("users", { _id: uuidv4(), name: "Alice", ssn: "123-45-6789" });
85
+
86
+ // Select by an unencrypted field
56
87
  const { data } = await aegis.select("users", { column: "name", value: "Alice" });
57
88
  // data[0].ssn → "123-45-6789" (decrypted)
58
89
  ```
@@ -62,7 +93,7 @@ const { data } = await aegis.select("users", { column: "name", value: "Alice" })
62
93
  Implement the `DatabaseAdapter` interface for any database:
63
94
 
64
95
  ```typescript
65
- import { DatabaseAdapter, AegisClient } from "aegis-lock";
96
+ import { DatabaseAdapter } from "aegis-lock";
66
97
 
67
98
  class MyAdapter implements DatabaseAdapter {
68
99
  async insert(table: string, data: Record<string, unknown>) {
@@ -78,26 +109,35 @@ class MyAdapter implements DatabaseAdapter {
78
109
 
79
110
  ## API
80
111
 
81
- ### `new AegisClient(adapter, key, encryptedFields)`
82
- - `adapter` — any `DatabaseAdapter` (SupabaseAdapter, MongoDBAdapter, or custom)
83
- - `key` — CryptoKey from `generateKey()` or `importKey()`
84
- - `encryptedFields` `Record<tableName, fieldName[]>`
112
+ ### `new AegisClient(config, key, bidxKey?)`
113
+
114
+ * `config` — `AegisConfig` object:
115
+ * `adapter`: any `DatabaseAdapter` (SupabaseAdapter, MongoDBAdapter, or custom)
116
+ * `primaryKeyField`: `string` (The ID field used for cryptographic contextual binding)
117
+ * `encryptedFields`: `Record<tableName, fieldName[]>`
118
+ * `bidxFields`: *(Optional)* `Record<tableName, fieldName[]>`
119
+
120
+ * `key` — CryptoKey from `generateKey()` or `importKey()`
121
+ * `bidxKey` — *(Optional)* CryptoKey from `generateBidxKey()` or `importKey()`
85
122
 
86
123
  ### Adapters
87
- - `new SupabaseAdapter(supabaseClient)`
88
- - `new MongoDBAdapter(mongoDb)`
89
124
 
90
- ### Crypto
91
- - `generateKey()` / `exportKey(key)` / `importKey(base64)`
92
- - `encrypt(plaintext, key)` / `decrypt(payload, key)`
125
+ * `new SupabaseAdapter(supabaseClient)`
126
+ * `new MongoDBAdapter(mongoDb)`
127
+
128
+ ### Crypto Utilities
129
+
130
+ * `generateKey()` / `generateBidxKey()`
131
+ * `exportKey(key)` / `importKey(base64)`
93
132
 
94
- ## How It Works
133
+ ## How It Works (Security Architecture)
95
134
 
96
- - **Web Crypto API** (AES-256-GCM) runs in any modern browser or edge runtime
97
- - Each row gets a unique **IV** stored alongside the ciphertext
98
- - Encryption/decryption happens client-side your server never sees plaintext
99
- - Database-agnostic: swap adapters without changing application code
135
+ * **Web Crypto API (AES-256-GCM):** Runs natively in any modern browser or edge runtime.
136
+ * **Field-Level IVs:** Every single encrypted field gets a unique, mathematically random Initialization Vector (IV) stored as a composite string (`iv:ciphertext`) to prevent keystream reuse attacks.
137
+ * **Contextual Binding (AAD):** Ciphertexts are cryptographically bound to the row's `primaryKeyField`. If an attacker copies an encrypted SSN from User A and pastes it into User B's row, the decryption will strictly fail.
138
+ * **Blind Indexing (HMAC-SHA256):** Because AES-GCM is non-deterministic (the same text encrypts differently every time), you cannot query standard encrypted fields. If configured via `bidxFields`, Aegis-Lock automatically generates deterministic, memory-aligned HMAC hashes. This allows you to search for exact matches (like looking up an email address) without exposing the plaintext to the database.
139
+ * **Database-agnostic:** Swap adapters without changing your core application code.
100
140
 
101
141
  ## License
102
142
 
103
- MIT
143
+ MIT
package/dist/client.d.ts CHANGED
@@ -1,15 +1,16 @@
1
- import type { DatabaseAdapter } from "./types";
1
+ import type { DatabaseAdapter, AegisConfig } from "./types";
2
2
  export declare class AegisClient {
3
3
  private adapter;
4
4
  private key;
5
+ private bidxKey?;
5
6
  private encryptedFields;
6
- constructor(adapter: DatabaseAdapter, key: CryptoKey, encryptedFields: Record<string, string[]>);
7
- /** Insert a row, auto-encrypting configured fields. Returns a shared IV for the row. */
7
+ private bidxFields;
8
+ private primaryKeyField;
9
+ constructor(config: AegisConfig, key: CryptoKey, bidxKey?: CryptoKey);
8
10
  insert(table: string, data: Record<string, unknown>): Promise<{
9
11
  data: Record<string, unknown>[] | null;
10
12
  error: unknown;
11
13
  }>;
12
- /** Select rows, auto-decrypting configured fields. */
13
14
  select(table: string, query?: {
14
15
  column?: string;
15
16
  value?: unknown;
@@ -18,7 +19,6 @@ export declare class AegisClient {
18
19
  data: Record<string, unknown>[] | null;
19
20
  error: unknown;
20
21
  }>;
21
- /** Select rows WITHOUT decrypting — exposes raw ciphertext. */
22
22
  selectRaw(table: string, query?: {
23
23
  column?: string;
24
24
  value?: unknown;
@@ -27,7 +27,6 @@ export declare class AegisClient {
27
27
  data: Record<string, unknown>[] | null;
28
28
  error: unknown;
29
29
  }>;
30
- /** Access the underlying database adapter. */
31
30
  get db(): DatabaseAdapter;
32
31
  }
33
32
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG/C,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,eAAe,CAA2B;gBAEtC,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAM/F,wFAAwF;IAClF,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;IAsBzD,sDAAsD;IAChD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;IAgCxF,+DAA+D;IACzD,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;IAI3F,8CAA8C;IAC9C,IAAI,EAAE,IAAI,eAAe,CAExB;CACF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG5D,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,eAAe,CAAS;gBAGpB,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,SAAS;IAS9D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;IAyCnD,MAAM,CACV,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;IA6DxD,SAAS,CACb,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;IAK9D,IAAI,EAAE,IAAI,eAAe,CAExB;CACF"}
package/dist/client.js CHANGED
@@ -1,31 +1,59 @@
1
- import { encrypt, decrypt } from "./crypto";
1
+ import { encrypt, decrypt, generateBlindIndex } from "./crypto";
2
2
  export class AegisClient {
3
- constructor(adapter, key, encryptedFields) {
4
- this.adapter = adapter;
3
+ // Updated constructor to accept the optional BIDX key
4
+ constructor(config, key, bidxKey) {
5
+ this.adapter = config.adapter;
5
6
  this.key = key;
6
- this.encryptedFields = encryptedFields;
7
+ this.bidxKey = bidxKey;
8
+ this.encryptedFields = config.encryptedFields;
9
+ this.bidxFields = config.bidxFields || {};
10
+ this.primaryKeyField = config.primaryKeyField;
7
11
  }
8
- /** Insert a row, auto-encrypting configured fields. Returns a shared IV for the row. */
9
12
  async insert(table, data) {
10
13
  const fields = this.encryptedFields[table] || [];
14
+ const bidxFields = this.bidxFields[table] || [];
11
15
  const row = { ...data };
12
- // Generate a single IV and reuse it for all fields in this row
13
- const ivBuffer = crypto.getRandomValues(new Uint8Array(12));
14
- const sharedIv = btoa(String.fromCharCode(...ivBuffer));
15
- for (const field of fields) {
16
- if (row[field] != null) {
17
- const { ciphertext } = await encrypt(String(row[field]), this.key, ivBuffer);
18
- row[field] = ciphertext;
16
+ if (fields.length > 0 || bidxFields.length > 0) {
17
+ const rowId = row[this.primaryKeyField];
18
+ if (!rowId) {
19
+ throw new Error(`Aegis: Cannot encrypt. Missing primary key '${this.primaryKeyField}' in payload.`);
20
+ }
21
+ const aadContext = String(rowId);
22
+ // 1. Handle Blind Indexing FIRST (While row data is still plaintext)
23
+ for (const field of bidxFields) {
24
+ if (row[field] != null && this.bidxKey) {
25
+ row[`${field}_bidx`] = await generateBlindIndex(String(row[field]), // Safe: This is still "alice@example.com"
26
+ this.bidxKey);
27
+ }
28
+ }
29
+ // 2. Handle Encryption SECOND (This overwrites the plaintext)
30
+ for (const field of fields) {
31
+ if (row[field] != null) {
32
+ const { ciphertext, iv } = await encrypt(String(row[field]), this.key, aadContext);
33
+ row[field] = `${iv}:${ciphertext}`;
34
+ }
19
35
  }
20
- }
21
- if (fields.length > 0) {
22
- row.iv = sharedIv;
23
36
  }
24
37
  return this.adapter.insert(table, row);
25
38
  }
26
- /** Select rows, auto-decrypting configured fields. */
27
39
  async select(table, query) {
28
- const { data, error } = await this.adapter.select(table, query);
40
+ // Intercept and swap query for Blind Indexing (NEW)
41
+ const bidxFields = this.bidxFields[table] || [];
42
+ let activeQuery = query;
43
+ // Make sure this uses THIS.bidxKey
44
+ // Inside your select method in client.ts
45
+ if (query?.column &&
46
+ query?.value &&
47
+ bidxFields.includes(query.column) &&
48
+ this.bidxKey) {
49
+ const blindIndexValue = await generateBlindIndex(String(query.value), this.bidxKey);
50
+ activeQuery = {
51
+ ...query,
52
+ column: `${query.column}_bidx`,
53
+ value: blindIndexValue, // Pass the resulting string
54
+ };
55
+ }
56
+ const { data, error } = await this.adapter.select(table, activeQuery);
29
57
  if (error || !data)
30
58
  return { data, error };
31
59
  const fields = this.encryptedFields[table] || [];
@@ -33,16 +61,19 @@ export class AegisClient {
33
61
  return { data, error };
34
62
  const decrypted = await Promise.all(data.map(async (row) => {
35
63
  const decRow = { ...row };
36
- const iv = row.iv;
37
- if (!iv)
64
+ const rowId = decRow[this.primaryKeyField];
65
+ if (!rowId)
38
66
  return decRow;
67
+ const aadContext = String(rowId);
39
68
  for (const field of fields) {
40
- if (decRow[field] != null) {
69
+ const payload = decRow[field];
70
+ if (typeof payload === "string" && payload.includes(":")) {
71
+ const [iv, ciphertext] = payload.split(":");
41
72
  try {
42
- decRow[field] = await decrypt({ ciphertext: String(decRow[field]), iv }, this.key);
73
+ decRow[field] = await decrypt({ ciphertext, iv }, this.key, aadContext);
43
74
  }
44
75
  catch {
45
- // leave as ciphertext if decryption fails
76
+ // Tampering detected
46
77
  }
47
78
  }
48
79
  }
@@ -50,13 +81,145 @@ export class AegisClient {
50
81
  }));
51
82
  return { data: decrypted, error };
52
83
  }
53
- /** Select rows WITHOUT decrypting — exposes raw ciphertext. */
54
84
  async selectRaw(table, query) {
55
85
  return this.adapter.select(table, query);
56
86
  }
57
- /** Access the underlying database adapter. */
58
87
  get db() {
59
88
  return this.adapter;
60
89
  }
61
90
  }
91
+ // export class AegisClient {
92
+ // private adapter: DatabaseAdapter;
93
+ // private key: CryptoKey;
94
+ // private bidxKey?: CryptoKey;
95
+ // private encryptedFields: Record<string, string[]>;
96
+ // private bidxFields: Record<string, string[]>;
97
+ // private primaryKeyField: string;
98
+ // constructor(config: AegisConfig, key: CryptoKey) {
99
+ // this.adapter = config.adapter;
100
+ // this.key = key;
101
+ // this.bidxKey = bidxKey;
102
+ // this.encryptedFields = config.encryptedFields;
103
+ // this.bidxFields = config.bidxFields || {};
104
+ // this.primaryKeyField = config.primaryKeyField;
105
+ // }
106
+ // async insert(table: string, data: Record<string, unknown>) {
107
+ // const fields = this.encryptedFields[table] || [];
108
+ // const row: Record<string, unknown> = { ...data };
109
+ // if (fields.length > 0) {
110
+ // const rowId = row[this.primaryKeyField];
111
+ // if (!rowId) {
112
+ // throw new Error(`Aegis: Cannot encrypt. Missing primary key '${this.primaryKeyField}' in payload.`);
113
+ // }
114
+ // const aadContext = String(rowId);
115
+ // for (const field of fields) {
116
+ // if (row[field] != null) {
117
+ // // Generates unique IV per field and binds to the row ID
118
+ // const { ciphertext, iv } = await encrypt(String(row[field]), this.key, aadContext);
119
+ // row[field] = `${iv}:${ciphertext}`;
120
+ // }
121
+ // }
122
+ // }
123
+ // return this.adapter.insert(table, row);
124
+ // }
125
+ // async select(table: string, query?: { column?: string; value?: unknown; limit?: number }) {
126
+ // const { data, error } = await this.adapter.select(table, query);
127
+ // if (error || !data) return { data, error };
128
+ // const fields = this.encryptedFields[table] || [];
129
+ // if (fields.length === 0) return { data, error };
130
+ // const decrypted = await Promise.all(
131
+ // data.map(async (row: Record<string, unknown>) => {
132
+ // const decRow = { ...row };
133
+ // const rowId = decRow[this.primaryKeyField];
134
+ // if (!rowId) return decRow; // Cannot decrypt without context
135
+ // const aadContext = String(rowId);
136
+ // for (const field of fields) {
137
+ // const payload = decRow[field];
138
+ // if (typeof payload === 'string' && payload.includes(':')) {
139
+ // const [iv, ciphertext] = payload.split(':');
140
+ // try {
141
+ // decRow[field] = await decrypt({ ciphertext, iv }, this.key, aadContext);
142
+ // } catch {
143
+ // // Tampering detected (invalid tag or swapped ciphertext). Leave as raw string.
144
+ // }
145
+ // }
146
+ // }
147
+ // return decRow;
148
+ // })
149
+ // );
150
+ // return { data: decrypted, error };
151
+ // }
152
+ // async selectRaw(table: string, query?: { column?: string; value?: unknown; limit?: number }) {
153
+ // return this.adapter.select(table, query);
154
+ // }
155
+ // get db(): DatabaseAdapter {
156
+ // return this.adapter;
157
+ // }
158
+ // }
159
+ // import type { DatabaseAdapter } from "./types";
160
+ // import { encrypt, decrypt } from "./crypto";
161
+ // export class AegisClient {
162
+ // private adapter: DatabaseAdapter;
163
+ // private key: CryptoKey;
164
+ // private encryptedFields: Record<string, string[]>;
165
+ // constructor(adapter: DatabaseAdapter, key: CryptoKey, encryptedFields: Record<string, string[]>) {
166
+ // this.adapter = adapter;
167
+ // this.key = key;
168
+ // this.encryptedFields = encryptedFields;
169
+ // }
170
+ // /** Insert a row, auto-encrypting configured fields. Returns a shared IV for the row. */
171
+ // async insert(table: string, data: Record<string, unknown>) {
172
+ // const fields = this.encryptedFields[table] || [];
173
+ // const row: Record<string, unknown> = { ...data };
174
+ // // Generate a single IV and reuse it for all fields in this row
175
+ // const ivBuffer = crypto.getRandomValues(new Uint8Array(12));
176
+ // const sharedIv = btoa(String.fromCharCode(...ivBuffer));
177
+ // for (const field of fields) {
178
+ // if (row[field] != null) {
179
+ // const { ciphertext } = await encrypt(String(row[field]), this.key, ivBuffer);
180
+ // row[field] = ciphertext;
181
+ // }
182
+ // }
183
+ // if (fields.length > 0) {
184
+ // row.iv = sharedIv;
185
+ // }
186
+ // return this.adapter.insert(table, row);
187
+ // }
188
+ // /** Select rows, auto-decrypting configured fields. */
189
+ // async select(table: string, query?: { column?: string; value?: unknown; limit?: number }) {
190
+ // const { data, error } = await this.adapter.select(table, query);
191
+ // if (error || !data) return { data, error };
192
+ // const fields = this.encryptedFields[table] || [];
193
+ // if (fields.length === 0) return { data, error };
194
+ // const decrypted = await Promise.all(
195
+ // data.map(async (row: Record<string, unknown>) => {
196
+ // const decRow = { ...row };
197
+ // const iv = row.iv as string;
198
+ // if (!iv) return decRow;
199
+ // for (const field of fields) {
200
+ // if (decRow[field] != null) {
201
+ // try {
202
+ // decRow[field] = await decrypt(
203
+ // { ciphertext: String(decRow[field]), iv },
204
+ // this.key
205
+ // );
206
+ // } catch {
207
+ // // leave as ciphertext if decryption fails
208
+ // }
209
+ // }
210
+ // }
211
+ // return decRow;
212
+ // })
213
+ // );
214
+ // return { data: decrypted, error };
215
+ // }
216
+ // /** Select rows WITHOUT decrypting — exposes raw ciphertext. */
217
+ // async selectRaw(table: string, query?: { column?: string; value?: unknown; limit?: number }) {
218
+ // return this.adapter.select(table, query);
219
+ // }
220
+ // /** Access the underlying database adapter. */
221
+ // get db(): DatabaseAdapter {
222
+ // return this.adapter;
223
+ // }
224
+ // }
62
225
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../client.ts"],"names":[],"mappings":"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"}
package/dist/crypto.d.ts CHANGED
@@ -2,6 +2,10 @@ import { EncryptedPayload } from "./types";
2
2
  export declare function generateKey(): Promise<CryptoKey>;
3
3
  export declare function exportKey(key: CryptoKey): Promise<string>;
4
4
  export declare function importKey(base64: string): Promise<CryptoKey>;
5
- export declare function encrypt(plaintext: string, key: CryptoKey, existingIv?: Uint8Array): Promise<EncryptedPayload>;
6
- export declare function decrypt(payload: EncryptedPayload, key: CryptoKey): Promise<string>;
5
+ export declare function encrypt(plaintext: string, key: CryptoKey, aadContext: string): Promise<EncryptedPayload>;
6
+ export declare function decrypt(payload: EncryptedPayload, key: CryptoKey, aadContext: string): Promise<string>;
7
+ /** Generates a dedicated key for deterministic Blind Indexing */
8
+ export declare function generateBidxKey(): Promise<CryptoKey>;
9
+ /** Generates a deterministic hash for database searching */
10
+ export declare function generateBlindIndex(plaintext: string, key: CryptoKey): Promise<string>;
7
11
  //# sourceMappingURL=crypto.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAK3C,wBAAsB,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAMtD;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/D;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAMlE;AAED,wBAAsB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAQnH;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAKxF"}
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA0B3C,wBAAsB,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAKtD;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/D;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CASlE;AAED,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,CAAC,CAsB3B;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAID,iEAAiE;AACjE,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAK1D;AAED,4DAA4D;AAC5D,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,SAAS,GACb,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
package/dist/crypto.js CHANGED
@@ -1,32 +1,116 @@
1
1
  const ALGO = "AES-GCM";
2
2
  const KEY_LENGTH = 256;
3
+ // Memory-safe Base64 conversion helpers
4
+ function bufferToBase64(buffer) {
5
+ let binary = "";
6
+ // Normalize to Uint8Array safely
7
+ const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
8
+ const len = bytes.byteLength;
9
+ for (let i = 0; i < len; i++) {
10
+ binary += String.fromCharCode(bytes[i]);
11
+ }
12
+ return btoa(binary);
13
+ }
14
+ function base64ToBuffer(base64) {
15
+ const binaryString = atob(base64);
16
+ const bytes = new Uint8Array(binaryString.length);
17
+ for (let i = 0; i < binaryString.length; i++) {
18
+ bytes[i] = binaryString.charCodeAt(i);
19
+ }
20
+ return bytes;
21
+ }
3
22
  export async function generateKey() {
4
- return crypto.subtle.generateKey({ name: ALGO, length: KEY_LENGTH }, true, ["encrypt", "decrypt"]);
23
+ return crypto.subtle.generateKey({ name: ALGO, length: KEY_LENGTH }, true, [
24
+ "encrypt",
25
+ "decrypt",
26
+ ]);
5
27
  }
6
28
  export async function exportKey(key) {
7
29
  const raw = await crypto.subtle.exportKey("raw", key);
8
- return btoa(String.fromCharCode(...new Uint8Array(raw)));
30
+ return bufferToBase64(raw);
9
31
  }
10
32
  export async function importKey(base64) {
11
- const raw = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
12
- return crypto.subtle.importKey("raw", raw, { name: ALGO, length: KEY_LENGTH }, true, [
13
- "encrypt",
14
- "decrypt",
15
- ]);
33
+ const raw = base64ToBuffer(base64);
34
+ return crypto.subtle.importKey("raw", raw, { name: ALGO, length: KEY_LENGTH }, true, ["encrypt", "decrypt"]);
16
35
  }
17
- export async function encrypt(plaintext, key, existingIv) {
18
- const iv = existingIv ? new Uint8Array(existingIv) : crypto.getRandomValues(new Uint8Array(12));
36
+ export async function encrypt(plaintext, key, aadContext) {
37
+ const iv = crypto.getRandomValues(new Uint8Array(12)); // ALWAYS unique
19
38
  const encoded = new TextEncoder().encode(plaintext);
20
- const cipherBuffer = await crypto.subtle.encrypt({ name: ALGO, iv }, key, encoded);
21
- return {
22
- ciphertext: btoa(String.fromCharCode(...new Uint8Array(cipherBuffer))),
23
- iv: btoa(String.fromCharCode(...iv)),
39
+ const algorithm = {
40
+ name: ALGO,
41
+ iv: iv,
24
42
  };
43
+ if (aadContext) {
44
+ algorithm.additionalData = new TextEncoder().encode(aadContext);
45
+ }
46
+ const cipherBuffer = await crypto.subtle.encrypt(algorithm, key, encoded);
47
+ return { ciphertext: bufferToBase64(cipherBuffer), iv: bufferToBase64(iv) };
25
48
  }
26
- export async function decrypt(payload, key) {
27
- const cipherBytes = Uint8Array.from(atob(payload.ciphertext), (c) => c.charCodeAt(0));
28
- const iv = Uint8Array.from(atob(payload.iv), (c) => c.charCodeAt(0));
29
- const decrypted = await crypto.subtle.decrypt({ name: ALGO, iv }, key, cipherBytes);
49
+ export async function decrypt(payload, key, aadContext) {
50
+ const cipherBytes = base64ToBuffer(payload.ciphertext);
51
+ const iv = base64ToBuffer(payload.iv);
52
+ const algorithm = {
53
+ name: ALGO,
54
+ iv: iv,
55
+ };
56
+ if (aadContext) {
57
+ algorithm.additionalData = new TextEncoder().encode(aadContext);
58
+ }
59
+ const decrypted = await crypto.subtle.decrypt(algorithm, key, cipherBytes);
30
60
  return new TextDecoder().decode(decrypted);
31
61
  }
62
+ const HMAC_ALGO = "HMAC";
63
+ /** Generates a dedicated key for deterministic Blind Indexing */
64
+ export async function generateBidxKey() {
65
+ return crypto.subtle.generateKey({ name: HMAC_ALGO, hash: "SHA-256" }, true, [
66
+ "sign",
67
+ "verify",
68
+ ]);
69
+ }
70
+ /** Generates a deterministic hash for database searching */
71
+ export async function generateBlindIndex(plaintext, key) {
72
+ const encoder = new TextEncoder();
73
+ const encoded = encoder.encode(plaintext);
74
+ // PRODUCTION FIX: Isolated buffer extraction.
75
+ // This ensures the HMAC signature is deterministic regardless of memory alignment.
76
+ const cleanBuffer = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
77
+ const signature = await crypto.subtle.sign("HMAC", key, cleanBuffer);
78
+ return bufferToBase64(signature);
79
+ }
80
+ // import { EncryptedPayload } from "./types";
81
+ // const ALGO = "AES-GCM";
82
+ // const KEY_LENGTH = 256;
83
+ // export async function generateKey(): Promise<CryptoKey> {
84
+ // return crypto.subtle.generateKey(
85
+ // { name: ALGO, length: KEY_LENGTH },
86
+ // true,
87
+ // ["encrypt", "decrypt"]
88
+ // );
89
+ // }
90
+ // export async function exportKey(key: CryptoKey): Promise<string> {
91
+ // const raw = await crypto.subtle.exportKey("raw", key);
92
+ // return btoa(String.fromCharCode(...new Uint8Array(raw)));
93
+ // }
94
+ // export async function importKey(base64: string): Promise<CryptoKey> {
95
+ // const raw = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
96
+ // return crypto.subtle.importKey("raw", raw, { name: ALGO, length: KEY_LENGTH }, true, [
97
+ // "encrypt",
98
+ // "decrypt",
99
+ // ]);
100
+ // }
101
+ // export async function encrypt(plaintext: string, key: CryptoKey, existingIv?: Uint8Array): Promise<EncryptedPayload> {
102
+ // const iv = existingIv ? new Uint8Array(existingIv) : crypto.getRandomValues(new Uint8Array(12));
103
+ // const encoded = new TextEncoder().encode(plaintext);
104
+ // const cipherBuffer = await crypto.subtle.encrypt({ name: ALGO, iv }, key, encoded);
105
+ // return {
106
+ // ciphertext: btoa(String.fromCharCode(...new Uint8Array(cipherBuffer))),
107
+ // iv: btoa(String.fromCharCode(...iv)),
108
+ // };
109
+ // }
110
+ // export async function decrypt(payload: EncryptedPayload, key: CryptoKey): Promise<string> {
111
+ // const cipherBytes = Uint8Array.from(atob(payload.ciphertext), (c) => c.charCodeAt(0));
112
+ // const iv = Uint8Array.from(atob(payload.iv), (c) => c.charCodeAt(0));
113
+ // const decrypted = await crypto.subtle.decrypt({ name: ALGO, iv }, key, cipherBytes);
114
+ // return new TextDecoder().decode(decrypted);
115
+ // }
32
116
  //# sourceMappingURL=crypto.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAAG,SAAS,CAAC;AACvB,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,WAAW,CAC9B,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,EAClC,IAAI,EACJ,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAc;IAC5C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc;IAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE;QACnF,SAAS;QACT,SAAS;KACV,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,SAAiB,EAAE,GAAc,EAAE,UAAuB;IACtF,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAChG,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACnF,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;QACtE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAyB,EAAE,GAAc;IACrE,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACtF,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;IACpF,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC"}
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,11 +1,8 @@
1
- /** Generic database adapter interface — implement this for any database. */
2
1
  export interface DatabaseAdapter {
3
- /** Insert a row into a table/collection. Returns the inserted data. */
4
2
  insert(table: string, data: Record<string, unknown>): Promise<{
5
3
  data: Record<string, unknown>[] | null;
6
4
  error: unknown;
7
5
  }>;
8
- /** Select rows from a table/collection with optional filters. */
9
6
  select(table: string, query?: {
10
7
  column?: string;
11
8
  value?: unknown;
@@ -18,6 +15,8 @@ export interface DatabaseAdapter {
18
15
  export interface AegisConfig {
19
16
  adapter: DatabaseAdapter;
20
17
  encryptedFields: Record<string, string[]>;
18
+ primaryKeyField: string;
19
+ bidxFields?: Record<string, string[]>;
21
20
  }
22
21
  export interface EncryptedPayload {
23
22
  ciphertext: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAE1H,iEAAiE;IACjE,MAAM,CACJ,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3D,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACxE;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1H,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC1J;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB"}
package/dist/types.js CHANGED
@@ -1,2 +1,24 @@
1
1
  export {};
2
+ // /** Generic database adapter interface — implement this for any database. */
3
+ // export interface DatabaseAdapter {
4
+ // /** Insert a row into a table/collection. Returns the inserted data. */
5
+ // insert(table: string, data: Record<string, unknown>): Promise<{ data: Record<string, unknown>[] | null; error: unknown }>;
6
+ // /** Select rows from a table/collection with optional filters. */
7
+ // select(
8
+ // table: string,
9
+ // query?: { column?: string; value?: unknown; limit?: number }
10
+ // ): Promise<{ data: Record<string, unknown>[] | null; error: unknown }>;
11
+ // }
12
+ // export interface AegisConfig {
13
+ // adapter: DatabaseAdapter;
14
+ // encryptedFields: Record<string, string[]>;
15
+ // }
16
+ // export interface EncryptedPayload {
17
+ // ciphertext: string;
18
+ // iv: string;
19
+ // }
20
+ // export interface AegisKeyPair {
21
+ // key: CryptoKey;
22
+ // exported: string;
23
+ // }
2
24
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":";AAqBA,+EAA+E;AAC/E,qCAAqC;AACrC,4EAA4E;AAC5E,+HAA+H;AAE/H,sEAAsE;AACtE,YAAY;AACZ,qBAAqB;AACrB,mEAAmE;AACnE,4EAA4E;AAC5E,IAAI;AAEJ,iCAAiC;AACjC,8BAA8B;AAC9B,+CAA+C;AAC/C,IAAI;AAEJ,sCAAsC;AACtC,wBAAwB;AACxB,gBAAgB;AAChB,IAAI;AAEJ,kCAAkC;AAClC,oBAAoB;AACpB,sBAAsB;AACtB,IAAI"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aegis-lock",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Database-agnostic client-side AES-256-GCM field-level encryption. Works with Supabase, MongoDB, or any database via pluggable adapters.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,7 +26,8 @@
26
26
  ],
27
27
  "scripts": {
28
28
  "build": "tsc -p tsconfig.build.json",
29
- "prepublishOnly": "npm run build"
29
+ "prepublishOnly": "npm run build",
30
+ "test": "jest"
30
31
  },
31
32
  "keywords": [
32
33
  "encryption",
@@ -53,6 +54,10 @@
53
54
  },
54
55
  "devDependencies": {
55
56
  "@supabase/supabase-js": "^2.0.0",
57
+ "@types/jest": "^30.0.0",
58
+ "@types/node": "^25.3.5",
59
+ "jest": "^30.2.0",
60
+ "ts-jest": "^29.4.6",
56
61
  "typescript": "^5.9.3"
57
62
  }
58
63
  }