aegis-lock 2.1.0 → 2.2.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/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # aegis-lock
2
2
 
3
- [![npm version](https://badge.fury.io/js/aegis-lock.svg)](https://badge.fury.io/js/aegis-lock)
3
+ [![npm version](https://badge.fury.io/js/aegis-lock.svg?v=2.1.0)](https://badge.fury.io/js/aegis-lock)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- **Database-agnostic client-side AES-256-GCM field-level encryption with Contextual Binding and Blind Indexing.**
6
+ **Database-agnostic client-side AES-256-GCM field-level encryption with Contextual Binding, Blind Indexing, and Seamless Key Rotation.**
7
7
 
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.
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.
9
9
 
10
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
11
 
@@ -22,17 +22,22 @@ npm install aegis-lock
22
22
 
23
23
  ```typescript
24
24
  import { createClient } from "@supabase/supabase-js";
25
- import { AegisClient, SupabaseAdapter, generateKey, generateBidxKey, exportKey } from "aegis-lock";
25
+ import { AegisClient, SupabaseAdapter, importKey, generateBidxKey } from "aegis-lock";
26
26
 
27
27
  const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
28
28
  const adapter = new SupabaseAdapter(supabase);
29
29
 
30
- // Generate your master encryption key and searchable blind index key
31
- const key = await generateKey();
32
- const bidxKey = await generateBidxKey();
30
+ // 1. Setup your Key Ring for Key Rotation
31
+ // You should load these base64 strings securely from your environment variables
32
+ const keyRing = {
33
+ "v1": await importKey(process.env.AEGIS_KEY_V1),
34
+ "v2": await importKey(process.env.AEGIS_KEY_V2) // Your newest key
35
+ };
36
+ const activeVersion = "v2";
33
37
 
34
- // Export and save these securely! e.g., await exportKey(key)
38
+ const bidxKey = await generateBidxKey(); // Or import your saved blind index key
35
39
 
40
+ // 2. Initialize the Client
36
41
  const aegis = new AegisClient({
37
42
  adapter,
38
43
  primaryKeyField: "record_id", // REQUIRED: Binds ciphertext to the row to prevent tampering
@@ -42,9 +47,9 @@ const aegis = new AegisClient({
42
47
  bidxFields: {
43
48
  secure_fields: ["email"] // Optional: Creates an 'email_bidx' column for searching
44
49
  }
45
- }, key, bidxKey);
50
+ }, keyRing, activeVersion, bidxKey);
46
51
 
47
- // 1. Insert — fields are auto-encrypted.
52
+ // 3. Insert — fields are auto-encrypted using the 'v2' key.
48
53
  // Note: You MUST provide the primary key application-side!
49
54
  await aegis.insert("secure_fields", {
50
55
  record_id: "uuid-1234-5678",
@@ -52,20 +57,21 @@ await aegis.insert("secure_fields", {
52
57
  encrypted_content: "Top secret",
53
58
  });
54
59
 
55
- // 2. Select — Aegis automatically hashes the email to search the 'email_bidx' column securely
60
+ // 4. Select — Aegis automatically hashes the email to search the 'email_bidx' column securely.
61
+ // It will dynamically select the correct key from the KeyRing to decrypt the results.
56
62
  const { data } = await aegis.select("secure_fields", {
57
63
  column: "email",
58
64
  value: "alice@example.com"
59
65
  });
60
66
 
61
- // 3. Update — automatically re-encrypts with a new IV and updates the blind index
67
+ // 5. Update — automatically re-encrypts with a new IV and the active 'v2' key.
62
68
  await aegis.update("secure_fields", {
63
69
  record_id: "uuid-1234-5678", // Must include the primary key!
64
70
  email: "new_alice@example.com",
65
71
  encrypted_content: "New secret"
66
72
  });
67
73
 
68
- // 4. Delete — Aegis automatically hashes the email to find the correct row to delete
74
+ // 6. Delete — Aegis automatically hashes the email to find the correct row to delete
69
75
  await aegis.delete("secure_fields", {
70
76
  column: "email",
71
77
  value: "new_alice@example.com"
@@ -76,14 +82,14 @@ await aegis.delete("secure_fields", {
76
82
 
77
83
  ```typescript
78
84
  import { MongoClient } from "mongodb";
79
- import { AegisClient, MongoDBAdapter, generateKey } from "aegis-lock";
85
+ import { AegisClient, MongoDBAdapter, importKey } from "aegis-lock";
80
86
  import { v4 as uuidv4 } from "uuid";
81
87
 
82
88
  const mongo = new MongoClient("mongodb://localhost:27017");
83
89
  await mongo.connect();
84
90
  const adapter = new MongoDBAdapter(mongo.db("myapp"));
85
91
 
86
- const key = await generateKey();
92
+ const keyRing = { "v1": await importKey(process.env.AEGIS_MASTER_KEY) };
87
93
 
88
94
  const aegis = new AegisClient({
89
95
  adapter,
@@ -91,36 +97,23 @@ const aegis = new AegisClient({
91
97
  encryptedFields: {
92
98
  users: ["ssn", "credit_card"]
93
99
  }
94
- }, key);
100
+ }, keyRing, "v1");
95
101
 
96
102
  const newUserId = uuidv4();
97
103
 
98
- // 1. Insert with a client-generated ID
104
+ // Insert with a client-generated ID
99
105
  await aegis.insert("users", {
100
106
  _id: newUserId,
101
107
  name: "Alice",
102
108
  ssn: "123-45-6789"
103
109
  });
104
110
 
105
- // 2. Select by an unencrypted field
111
+ // Select by an unencrypted field
106
112
  const { data } = await aegis.select("users", {
107
113
  column: "name",
108
114
  value: "Alice"
109
115
  });
110
116
  // data[0].ssn → "123-45-6789" (decrypted)
111
-
112
- // 3. Update — automatically re-encrypts the SSN with a new IV
113
- await aegis.update("users", {
114
- _id: newUserId, // Must include the primary key!
115
- name: "Alice",
116
- ssn: "999-99-9999"
117
- });
118
-
119
- // 4. Delete — Removes the record from the database
120
- await aegis.delete("users", {
121
- column: "_id",
122
- value: newUserId
123
- });
124
117
  ```
125
118
 
126
119
  ## Custom Adapter
@@ -152,23 +145,24 @@ class MyAdapter implements DatabaseAdapter {
152
145
 
153
146
  ## API
154
147
 
155
- ### `new AegisClient(config, key, bidxKey?)`
148
+ ### `new AegisClient(config, keyRing, currentKeyVersion, bidxKey?)`
156
149
 
157
- * `config` — `AegisConfig` object:
158
- * `adapter`: any `DatabaseAdapter` (`SupabaseAdapter`, `MongoDBAdapter`, or custom)
159
- * `primaryKeyField`: `string` (The ID field used for cryptographic contextual binding)
160
- * `encryptedFields`: `Record<tableName, fieldName[]>`
161
- * `bidxFields`: *(Optional)* `Record<tableName, fieldName[]>`
162
- * `key` — `CryptoKey` from `generateKey()` or `importKey()`
163
- * `bidxKey`*(Optional)* `CryptoKey` from `generateBidxKey()` or `importKey()`
150
+ * **`config`** — `AegisConfig` object:
151
+ * **`adapter`**: any `DatabaseAdapter` (`SupabaseAdapter`, `MongoDBAdapter`, or custom)
152
+ * **`primaryKeyField`**: `string` (The ID field used for cryptographic contextual binding)
153
+ * **`encryptedFields`**: `Record<tableName, fieldName[]>`
154
+ * **`bidxFields`**: *(Optional)* `Record<tableName, fieldName[]>`
155
+ * **`keyRing`** — `Record<string, CryptoKey>` (A dictionary of all active and historical keys).
156
+ * **`currentKeyVersion`** — `string` (The version tag of the key to use for *new* encryptions).
157
+ * **`bidxKey`** — *(Optional)* `CryptoKey` from `generateBidxKey()` or `importKey()`
164
158
 
165
159
  ### `AegisClient` Methods
166
160
 
167
- * `insert(table, data)`: Encrypts data and creates blind indexes before saving.
168
- * `select(table, query)`: Fetches and automatically decrypts data. Intercepts blind index queries.
169
- * `update(table, data)`: Re-encrypts modified fields with new IVs and updates blind indexes.
170
- * `delete(table, query)`: Intercepts queries to securely delete by blind-indexed fields.
171
- * `selectRaw(table, query)`: Bypasses decryption to return raw database records (useful for auditing or migrations).
161
+ * **`insert(table, data)`**: Encrypts data and creates blind indexes before saving.
162
+ * **`select(table, query)`**: Fetches and automatically decrypts data. Intercepts blind index queries.
163
+ * **`update(table, data)`**: Re-encrypts modified fields with new IVs and updates blind indexes.
164
+ * **`delete(table, query)`**: Intercepts queries to securely delete by blind-indexed fields.
165
+ * **`selectRaw(table, query)`**: Bypasses decryption to return raw database records (useful for auditing or migrations).
172
166
 
173
167
  ### Adapters
174
168
 
@@ -184,14 +178,13 @@ class MyAdapter implements DatabaseAdapter {
184
178
 
185
179
  ## How It Works (Security Architecture)
186
180
 
187
-
188
-
189
- * **Web Crypto API (AES-256-GCM):** Runs natively in any modern browser or edge runtime.
190
- * **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.
181
+ * **Web Crypto API (AES-256-GCM):** Runs natively in any modern browser or edge runtime without bloated dependencies.
182
+ * **Seamless Key Rotation:** Aegis-Lock accepts a dictionary of keys. It tags every database payload with the active key's version string. If a key is compromised, you simply introduce a `v2` key. New data is secured with `v2`, while historical data seamlessly decrypts using `v1` without a single second of database downtime.
183
+ * **Field-Level IVs:** Every single encrypted field gets a unique, mathematically random Initialization Vector (IV). The final database payload is formatted as `version:iv:ciphertext` to prevent keystream reuse attacks.
191
184
  * **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.
192
185
  * **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.
193
- * **Database-agnostic:** Swap adapters without changing your core application code.
186
+ * **Database-Agnostic:** Swap adapters without changing your core application code.
194
187
 
195
188
  ## License
196
189
 
197
- MIT
190
+ MIT
package/dist/client.d.ts CHANGED
@@ -1,29 +1,29 @@
1
1
  import type { DatabaseAdapter, AegisConfig } from "./types";
2
2
  /**
3
3
  * The primary client for aegis-lock.
4
- * Handles automatic encryption, decryption, contextual binding, and blind indexing
5
- * before interacting with the underlying database adapter.
4
+ * Handles automatic encryption, decryption, contextual binding, blind indexing,
5
+ * and Key Rotation before interacting with the underlying database adapter.
6
6
  */
7
7
  export declare class AegisClient {
8
8
  private adapter;
9
- private key;
9
+ private keyRing;
10
+ private currentKeyVersion;
10
11
  private bidxKey?;
11
12
  private encryptedFields;
12
13
  private bidxFields;
13
14
  private primaryKeyField;
14
15
  /**
15
- * Initializes the AegisClient.
16
- * * @param config - Configuration including the database adapter, primary key field, and field rules.
17
- * @param key - The master CryptoKey used for AES-GCM encryption.
16
+ * Initializes the AegisClient with Key Rotation support.
17
+ *
18
+ * @param config - Configuration including the database adapter, primary key field, and field rules.
19
+ * @param keyRing - A dictionary of historical and active CryptoKeys (e.g., { v1: key1, v2: key2 }).
20
+ * @param currentKeyVersion - The string identifier of the key to use for NEW encryptions (e.g., "v2").
18
21
  * @param bidxKey - (Optional) The CryptoKey used for generating HMAC-SHA256 blind indexes.
19
22
  */
20
- constructor(config: AegisConfig, key: CryptoKey, bidxKey?: CryptoKey);
23
+ constructor(config: AegisConfig, keyRing: Record<string, CryptoKey>, currentKeyVersion: string, bidxKey?: CryptoKey);
21
24
  /**
22
25
  * Securely inserts a new record into the database.
23
- * Automatically generates blind indexes and encrypts configured fields.
24
- * * @param table - The database table or collection name.
25
- * @param data - The plaintext data object to insert. Must include the primary key.
26
- * @returns The inserted data (as stored in the database) or an error.
26
+ * Automatically generates blind indexes and encrypts configured fields using the CURRENT key version.
27
27
  */
28
28
  insert(table: string, data: Record<string, unknown>): Promise<{
29
29
  data: Record<string, unknown>[] | null;
@@ -31,10 +31,7 @@ export declare class AegisClient {
31
31
  }>;
32
32
  /**
33
33
  * Retrieves and automatically decrypts records from the database.
34
- * If querying by a configured blind index field, the query is automatically intercepted and hashed.
35
- * * @param table - The database table or collection name.
36
- * @param query - The column and value to search for (e.g., { column: "email", value: "alice@example.com" }).
37
- * @returns The decrypted plaintext data or an error.
34
+ * Dynamically selects the correct decryption key based on the payload's version tag.
38
35
  */
39
36
  select(table: string, query?: {
40
37
  column?: string;
@@ -46,22 +43,12 @@ export declare class AegisClient {
46
43
  }>;
47
44
  /**
48
45
  * Securely modifies an existing record.
49
- * Re-encrypts data with a new unique IV and updates blind indexes.
50
- * * @param table - The database table or collection name.
51
- * @param data - The updated plaintext data. Must include the primary key.
52
- * @returns The updated data (as stored in the database) or an error.
46
+ * Re-encrypts data with a new unique IV and the CURRENT key version.
53
47
  */
54
48
  update(table: string, data: Record<string, unknown>): Promise<{
55
49
  data: any[] | null;
56
50
  error: any;
57
51
  }>;
58
- /**
59
- * Securely removes records from the database.
60
- * Automatically hashes the search query if deleting by a blind-indexed field.
61
- * * @param table - The database table or collection name.
62
- * @param query - The column and value to identify the record to delete.
63
- * @returns The result of the deletion operation or an error.
64
- */
65
52
  delete(table: string, query: {
66
53
  column: string;
67
54
  value: unknown;
@@ -69,13 +56,6 @@ export declare class AegisClient {
69
56
  data: any[] | null;
70
57
  error: any;
71
58
  }>;
72
- /**
73
- * Bypasses decryption and retrieves the raw, encrypted data directly from the database.
74
- * Useful for database migrations, auditing, or debugging.
75
- * * @param table - The database table or collection name.
76
- * @param query - The raw query to execute against the database.
77
- * @returns The raw, encrypted database rows.
78
- */
79
59
  selectRaw(table: string, query?: {
80
60
  column?: string;
81
61
  value?: unknown;
@@ -84,10 +64,6 @@ export declare class AegisClient {
84
64
  data: Record<string, unknown>[] | null;
85
65
  error: unknown;
86
66
  }>;
87
- /**
88
- * Gets the underlying database adapter instance.
89
- * Useful for executing custom database commands outside of Aegis's encryption flow.
90
- */
91
67
  get db(): DatabaseAdapter;
92
68
  }
93
69
  //# 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,WAAW,EAAE,MAAM,SAAS,CAAC;AAG5D;;;;GAIG;AACH,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;IAEhC;;;;;OAKG;gBACS,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,SAAS;IASpE;;;;;;OAMG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;IAyCzD;;;;;;OAMG;IACG,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;;;;IA6D9D;;;;;;OAMG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;IAkCzD;;;;;;OAMG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE;;;;IAkBrE;;;;;;OAMG;IACG,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;;;OAGG;IACH,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;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,eAAe,CAAS;IAEhC;;;;;;;OAOG;gBAED,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAClC,iBAAiB,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,SAAS;IAWrB;;;OAGG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;IA6CzD;;;OAGG;IACG,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;;;;IAgE9D;;;OAGG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;IAsCnD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE;;;;IAgB/D,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,30 +1,30 @@
1
1
  import { encrypt, decrypt, generateBlindIndex } from "./crypto";
2
2
  /**
3
3
  * The primary client for aegis-lock.
4
- * Handles automatic encryption, decryption, contextual binding, and blind indexing
5
- * before interacting with the underlying database adapter.
4
+ * Handles automatic encryption, decryption, contextual binding, blind indexing,
5
+ * and Key Rotation before interacting with the underlying database adapter.
6
6
  */
7
7
  export class AegisClient {
8
8
  /**
9
- * Initializes the AegisClient.
10
- * * @param config - Configuration including the database adapter, primary key field, and field rules.
11
- * @param key - The master CryptoKey used for AES-GCM encryption.
9
+ * Initializes the AegisClient with Key Rotation support.
10
+ *
11
+ * @param config - Configuration including the database adapter, primary key field, and field rules.
12
+ * @param keyRing - A dictionary of historical and active CryptoKeys (e.g., { v1: key1, v2: key2 }).
13
+ * @param currentKeyVersion - The string identifier of the key to use for NEW encryptions (e.g., "v2").
12
14
  * @param bidxKey - (Optional) The CryptoKey used for generating HMAC-SHA256 blind indexes.
13
15
  */
14
- constructor(config, key, bidxKey) {
16
+ constructor(config, keyRing, currentKeyVersion, bidxKey) {
15
17
  this.adapter = config.adapter;
16
- this.key = key;
17
- this.bidxKey = bidxKey; // Optional Blind Index Key
18
+ this.keyRing = keyRing;
19
+ this.currentKeyVersion = currentKeyVersion;
20
+ this.bidxKey = bidxKey;
18
21
  this.encryptedFields = config.encryptedFields;
19
22
  this.bidxFields = config.bidxFields || {};
20
23
  this.primaryKeyField = config.primaryKeyField;
21
24
  }
22
25
  /**
23
26
  * Securely inserts a new record into the database.
24
- * Automatically generates blind indexes and encrypts configured fields.
25
- * * @param table - The database table or collection name.
26
- * @param data - The plaintext data object to insert. Must include the primary key.
27
- * @returns The inserted data (as stored in the database) or an error.
27
+ * Automatically generates blind indexes and encrypts configured fields using the CURRENT key version.
28
28
  */
29
29
  async insert(table, data) {
30
30
  const fields = this.encryptedFields[table] || [];
@@ -36,18 +36,20 @@ export class AegisClient {
36
36
  throw new Error(`Aegis: Cannot encrypt. Missing primary key '${this.primaryKeyField}' in payload.`);
37
37
  }
38
38
  const aadContext = String(rowId);
39
- // 1. Handle Blind Indexing FIRST (While row data is still plaintext)
39
+ const activeKey = this.keyRing[this.currentKeyVersion]; // Grab the active key
40
+ // 1. Handle Blind Indexing FIRST
40
41
  for (const field of bidxFields) {
41
42
  if (row[field] != null && this.bidxKey) {
42
- row[`${field}_bidx`] = await generateBlindIndex(String(row[field]), // Safe: This is still "alice@example.com"
43
- this.bidxKey);
43
+ row[`${field}_bidx`] = await generateBlindIndex(String(row[field]), this.bidxKey);
44
44
  }
45
45
  }
46
- // 2. Handle Encryption SECOND (This overwrites the plaintext)
46
+ // 2. Handle Encryption SECOND
47
47
  for (const field of fields) {
48
48
  if (row[field] != null) {
49
- const { ciphertext, iv } = await encrypt(String(row[field]), this.key, aadContext);
50
- row[field] = `${iv}:${ciphertext}`;
49
+ // Pass the active key and the version tag to the new encrypt function
50
+ const { version, ciphertext, iv } = await encrypt(String(row[field]), activeKey, this.currentKeyVersion, aadContext);
51
+ // Store it in the DB as "version:iv:ciphertext"
52
+ row[field] = `${version}:${iv}:${ciphertext}`;
51
53
  }
52
54
  }
53
55
  }
@@ -55,17 +57,11 @@ export class AegisClient {
55
57
  }
56
58
  /**
57
59
  * Retrieves and automatically decrypts records from the database.
58
- * If querying by a configured blind index field, the query is automatically intercepted and hashed.
59
- * * @param table - The database table or collection name.
60
- * @param query - The column and value to search for (e.g., { column: "email", value: "alice@example.com" }).
61
- * @returns The decrypted plaintext data or an error.
60
+ * Dynamically selects the correct decryption key based on the payload's version tag.
62
61
  */
63
62
  async select(table, query) {
64
- // Intercept and swap query for Blind Indexing (NEW)
65
63
  const bidxFields = this.bidxFields[table] || [];
66
64
  let activeQuery = query;
67
- // Make sure this uses THIS.bidxKey
68
- // Inside your select method in client.ts
69
65
  if (query?.column &&
70
66
  query?.value &&
71
67
  bidxFields.includes(query.column) &&
@@ -74,7 +70,7 @@ export class AegisClient {
74
70
  activeQuery = {
75
71
  ...query,
76
72
  column: `${query.column}_bidx`,
77
- value: blindIndexValue, // Pass the resulting string
73
+ value: blindIndexValue,
78
74
  };
79
75
  }
80
76
  const { data, error } = await this.adapter.select(table, activeQuery);
@@ -90,14 +86,19 @@ export class AegisClient {
90
86
  return decRow;
91
87
  const aadContext = String(rowId);
92
88
  for (const field of fields) {
93
- const payload = decRow[field];
94
- if (typeof payload === "string" && payload.includes(":")) {
95
- const [iv, ciphertext] = payload.split(":");
96
- try {
97
- decRow[field] = await decrypt({ ciphertext, iv }, this.key, aadContext);
98
- }
99
- catch {
100
- // Tampering detected
89
+ const payloadStr = decRow[field];
90
+ if (typeof payloadStr === "string" && payloadStr.includes(":")) {
91
+ const parts = payloadStr.split(":");
92
+ // Check for our new 3-part versioned payload
93
+ if (parts.length === 3) {
94
+ const [version, iv, ciphertext] = parts;
95
+ try {
96
+ // Pass the whole KeyRing. crypto.ts will pick the right one.
97
+ decRow[field] = await decrypt({ version, ciphertext, iv }, this.keyRing, aadContext);
98
+ }
99
+ catch {
100
+ // Tampering detected or wrong key
101
+ }
101
102
  }
102
103
  }
103
104
  }
@@ -107,10 +108,7 @@ export class AegisClient {
107
108
  }
108
109
  /**
109
110
  * Securely modifies an existing record.
110
- * Re-encrypts data with a new unique IV and updates blind indexes.
111
- * * @param table - The database table or collection name.
112
- * @param data - The updated plaintext data. Must include the primary key.
113
- * @returns The updated data (as stored in the database) or an error.
111
+ * Re-encrypts data with a new unique IV and the CURRENT key version.
114
112
  */
115
113
  async update(table, data) {
116
114
  const fields = this.encryptedFields[table] || [];
@@ -121,35 +119,25 @@ export class AegisClient {
121
119
  throw new Error(`Aegis: Cannot update. Missing primary key '${this.primaryKeyField}' in payload.`);
122
120
  }
123
121
  const aadContext = String(rowId);
122
+ const activeKey = this.keyRing[this.currentKeyVersion];
124
123
  if (fields.length > 0 || bidxFields.length > 0) {
125
- // 1. Update Blind Indexes
126
124
  for (const field of bidxFields) {
127
125
  if (row[field] != null && this.bidxKey) {
128
126
  row[`${field}_bidx`] = await generateBlindIndex(String(row[field]), this.bidxKey);
129
127
  }
130
128
  }
131
- // 2. Encrypt updated fields with a brand new IV
132
129
  for (const field of fields) {
133
130
  if (row[field] != null) {
134
- const { ciphertext, iv } = await encrypt(String(row[field]), this.key, aadContext);
135
- row[field] = `${iv}:${ciphertext}`;
131
+ const { version, ciphertext, iv } = await encrypt(String(row[field]), activeKey, this.currentKeyVersion, aadContext);
132
+ row[field] = `${version}:${iv}:${ciphertext}`;
136
133
  }
137
134
  }
138
135
  }
139
136
  return this.adapter.update(table, row);
140
137
  }
141
- /**
142
- * Securely removes records from the database.
143
- * Automatically hashes the search query if deleting by a blind-indexed field.
144
- * * @param table - The database table or collection name.
145
- * @param query - The column and value to identify the record to delete.
146
- * @returns The result of the deletion operation or an error.
147
- */
148
138
  async delete(table, query) {
149
139
  const bidxFields = this.bidxFields[table] || [];
150
140
  let activeQuery = query;
151
- // Intercept the query! If they are deleting by an encrypted field (like email),
152
- // we must hash the value so the database knows which row to delete.
153
141
  if (bidxFields.includes(query.column) && this.bidxKey) {
154
142
  const blindIndexValue = await generateBlindIndex(String(query.value), this.bidxKey);
155
143
  activeQuery = {
@@ -160,20 +148,9 @@ export class AegisClient {
160
148
  }
161
149
  return this.adapter.delete(table, activeQuery);
162
150
  }
163
- /**
164
- * Bypasses decryption and retrieves the raw, encrypted data directly from the database.
165
- * Useful for database migrations, auditing, or debugging.
166
- * * @param table - The database table or collection name.
167
- * @param query - The raw query to execute against the database.
168
- * @returns The raw, encrypted database rows.
169
- */
170
151
  async selectRaw(table, query) {
171
152
  return this.adapter.select(table, query);
172
153
  }
173
- /**
174
- * Gets the underlying database adapter instance.
175
- * Useful for executing custom database commands outside of Aegis's encryption flow.
176
- */
177
154
  get db() {
178
155
  return this.adapter;
179
156
  }
@@ -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
@@ -21,22 +21,25 @@ export declare function importKey(base64: string): Promise<CryptoKey>;
21
21
  * Encrypts a plaintext string using AES-256-GCM.
22
22
  * Automatically generates a unique 12-byte Initialization Vector (IV) and applies
23
23
  * Contextual Binding (AAD) to tie the ciphertext to a specific database row.
24
- * * @param plaintext - The sensitive data to encrypt.
24
+ * @param plaintext - The sensitive data to encrypt.
25
25
  * @param key - The master AES-GCM CryptoKey.
26
+ * @param keyVersion - The string identifier for the active key (e.g., "v2").
26
27
  * @param aadContext - The row ID or primary key to bind this ciphertext to.
27
28
  * @returns A Promise resolving to an object containing the Base64 `ciphertext` and `iv`.
28
29
  */
29
- export declare function encrypt(plaintext: string, key: CryptoKey, aadContext: string): Promise<EncryptedPayload>;
30
+ export declare function encrypt(plaintext: string, key: CryptoKey, keyVersion: string, aadContext: string): Promise<EncryptedPayload>;
30
31
  /**
31
32
  * Decrypts an AES-256-GCM payload back into plaintext.
32
- * Strictly verifies the Additional Authenticated Data (AAD) to ensure the data
33
- * has not been tampered with or copied from another database row.
34
- * * @param payload - The object containing the Base64 `ciphertext` and `iv`.
35
- * @param key - The master AES-GCM CryptoKey.
33
+ * Supports Key Rotation by reading the payload's version and selecting the correct key.
34
+ * Strictly verifies the Context (AAD) to ensure data integrity.
35
+ *
36
+ * @param payload - The EncryptedPayload containing `version`, `ciphertext`, and `iv`.
37
+ * @param keyRing - A dictionary of historical and active CryptoKeys (e.g., { "v1": key1, "v2": key2 }).
36
38
  * @param aadContext - The row ID or primary key that this ciphertext is bound to.
37
39
  * @returns A Promise resolving to the decrypted plaintext string.
38
40
  */
39
- export declare function decrypt(payload: EncryptedPayload, key: CryptoKey, aadContext: string): Promise<string>;
41
+ export declare function decrypt(payload: EncryptedPayload, keyRing: Record<string, CryptoKey>, // Accepts multiple keys
42
+ aadContext: string): Promise<string>;
40
43
  /** * Generates a dedicated HMAC-SHA256 key for deterministic Blind Indexing.
41
44
  * This key should be kept separate from the master encryption key.
42
45
  * * @returns A Promise resolving to an HMAC CryptoKey.
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAqC3C;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAKtD;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/D;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CASlE;AAED;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,CAAC,CAsB3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAID;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAK1D;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,SAAS,GACb,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAqC3C;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAKtD;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/D;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CASlE;AAED;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,CAAC,CAsB3B;AAED;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,wBAAwB;AAC5D,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CA6BjB;AAID;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAK1D;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,SAAS,GACb,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
package/dist/crypto.js CHANGED
@@ -63,12 +63,13 @@ export async function importKey(base64) {
63
63
  * Encrypts a plaintext string using AES-256-GCM.
64
64
  * Automatically generates a unique 12-byte Initialization Vector (IV) and applies
65
65
  * Contextual Binding (AAD) to tie the ciphertext to a specific database row.
66
- * * @param plaintext - The sensitive data to encrypt.
66
+ * @param plaintext - The sensitive data to encrypt.
67
67
  * @param key - The master AES-GCM CryptoKey.
68
+ * @param keyVersion - The string identifier for the active key (e.g., "v2").
68
69
  * @param aadContext - The row ID or primary key to bind this ciphertext to.
69
70
  * @returns A Promise resolving to an object containing the Base64 `ciphertext` and `iv`.
70
71
  */
71
- export async function encrypt(plaintext, key, aadContext) {
72
+ export async function encrypt(plaintext, key, keyVersion, aadContext) {
72
73
  const iv = crypto.getRandomValues(new Uint8Array(12)); // ALWAYS unique
73
74
  const encoded = new TextEncoder().encode(plaintext);
74
75
  const algorithm = {
@@ -79,18 +80,25 @@ export async function encrypt(plaintext, key, aadContext) {
79
80
  algorithm.additionalData = new TextEncoder().encode(aadContext);
80
81
  }
81
82
  const cipherBuffer = await crypto.subtle.encrypt(algorithm, key, encoded);
82
- return { ciphertext: bufferToBase64(cipherBuffer), iv: bufferToBase64(iv) };
83
+ return { version: keyVersion, ciphertext: bufferToBase64(cipherBuffer), iv: bufferToBase64(iv) };
83
84
  }
84
85
  /**
85
86
  * Decrypts an AES-256-GCM payload back into plaintext.
86
- * Strictly verifies the Additional Authenticated Data (AAD) to ensure the data
87
- * has not been tampered with or copied from another database row.
88
- * * @param payload - The object containing the Base64 `ciphertext` and `iv`.
89
- * @param key - The master AES-GCM CryptoKey.
87
+ * Supports Key Rotation by reading the payload's version and selecting the correct key.
88
+ * Strictly verifies the Context (AAD) to ensure data integrity.
89
+ *
90
+ * @param payload - The EncryptedPayload containing `version`, `ciphertext`, and `iv`.
91
+ * @param keyRing - A dictionary of historical and active CryptoKeys (e.g., { "v1": key1, "v2": key2 }).
90
92
  * @param aadContext - The row ID or primary key that this ciphertext is bound to.
91
93
  * @returns A Promise resolving to the decrypted plaintext string.
92
94
  */
93
- export async function decrypt(payload, key, aadContext) {
95
+ export async function decrypt(payload, keyRing, // Accepts multiple keys
96
+ aadContext) {
97
+ // Identify which key to use based on the payload's version tag
98
+ const targetKey = keyRing[payload.version];
99
+ if (!targetKey) {
100
+ throw new Error(`CRITICAL: Key version [${payload.version}] not found in provided KeyRing.`);
101
+ }
94
102
  const cipherBytes = base64ToBuffer(payload.ciphertext);
95
103
  const iv = base64ToBuffer(payload.iv);
96
104
  const algorithm = {
@@ -100,7 +108,8 @@ export async function decrypt(payload, key, aadContext) {
100
108
  if (aadContext) {
101
109
  algorithm.additionalData = new TextEncoder().encode(aadContext);
102
110
  }
103
- const decrypted = await crypto.subtle.decrypt(algorithm, key, cipherBytes);
111
+ const decrypted = await crypto.subtle.decrypt(algorithm, targetKey, // Use the dynamically selected key
112
+ cipherBytes);
104
113
  return new TextDecoder().decode(decrypted);
105
114
  }
106
115
  const HMAC_ALGO = "HMAC";
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -30,6 +30,7 @@ export interface AegisConfig {
30
30
  bidxFields?: Record<string, string[]>;
31
31
  }
32
32
  export interface EncryptedPayload {
33
+ version: string;
33
34
  ciphertext: string;
34
35
  iv: string;
35
36
  }
@@ -1 +1 @@
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;IACzJ,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAClG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;CAC/G;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"}
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;IACzJ,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAClG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;CAC/G;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,OAAO,EAAE,MAAM,CAAC;IAChB,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/package.json CHANGED
@@ -1,7 +1,15 @@
1
1
  {
2
2
  "name": "aegis-lock",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Database-agnostic client-side AES-256-GCM field-level encryption. Works with Supabase, MongoDB, or any database via pluggable adapters.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/hritesh-saha/aegis-lock.git"
8
+ },
9
+ "bugs": {
10
+ "url": "https://github.com/hritesh-saha/aegis-lock/issues"
11
+ },
12
+ "homepage": "https://github.com/hritesh-saha/aegis-lock#readme",
5
13
  "type": "module",
6
14
  "main": "dist/index.js",
7
15
  "module": "dist/index.js",
@@ -50,6 +58,9 @@
50
58
  "peerDependenciesMeta": {
51
59
  "@supabase/supabase-js": {
52
60
  "optional": true
61
+ },
62
+ "mongodb": {
63
+ "optional": true
53
64
  }
54
65
  },
55
66
  "devDependencies": {
@@ -57,6 +68,7 @@
57
68
  "@types/jest": "^30.0.0",
58
69
  "@types/node": "^25.3.5",
59
70
  "jest": "^30.2.0",
71
+ "mongodb": "^7.1.1",
60
72
  "ts-jest": "^29.4.6",
61
73
  "typescript": "^5.9.3"
62
74
  }