@layer-ai/core 0.6.0 → 0.7.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/dist/index.d.ts CHANGED
@@ -7,6 +7,8 @@ export { authenticate } from './middleware/auth.js';
7
7
  export type {} from './middleware/auth.js';
8
8
  export { db } from './lib/db/postgres.js';
9
9
  export { default as redis } from './lib/db/redis.js';
10
+ export { encrypt, decrypt, generateEncryptionKey } from './lib/encryption.js';
11
+ export type { EncryptedData } from '@layer-ai/sdk';
10
12
  export declare const createSessionKey: (userId: string) => Promise<string>;
11
13
  export declare const deleteSessionKeysForUser: (userId: string) => Promise<void>;
12
14
  export * from './services/task-analysis.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG3C,OAAO,EAAE,EAAE,EAAE,MAAM,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,gBAAgB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,MAAM,CAGrE,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAG3E,CAAC;AAGF,cAAc,6BAA6B,CAAC;AAG5C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG3C,OAAO,EAAE,EAAE,EAAE,MAAM,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,eAAO,MAAM,gBAAgB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,MAAM,CAGrE,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAG3E,CAAC;AAGF,cAAc,6BAA6B,CAAC;AAG5C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC"}
package/dist/index.js CHANGED
@@ -9,6 +9,8 @@ export { authenticate } from './middleware/auth.js';
9
9
  // Database
10
10
  export { db } from './lib/db/postgres.js';
11
11
  export { default as redis } from './lib/db/redis.js';
12
+ // Encryption
13
+ export { encrypt, decrypt, generateEncryptionKey } from './lib/encryption.js';
12
14
  // Session Key Utilities (for Next.js auth)
13
15
  export const createSessionKey = async (userId) => {
14
16
  const { db } = await import('./lib/db/postgres.js');
@@ -1,5 +1,5 @@
1
1
  import pg from 'pg';
2
- import type { User, ApiKey, Gate } from '@layer-ai/sdk';
2
+ import type { User, ApiKey, Gate, ProviderKey } from '@layer-ai/sdk';
3
3
  declare function getPool(): pg.Pool;
4
4
  export declare const db: {
5
5
  query(text: string, params?: any[]): Promise<pg.QueryResult<any>>;
@@ -25,6 +25,21 @@ export declare const db: {
25
25
  } | null>;
26
26
  createSessionKey(userId: string): Promise<string>;
27
27
  deleteSessionKeysForUser(userId: string): Promise<void>;
28
+ getProviderKey(userId: string, provider: string): Promise<ProviderKey | null>;
29
+ getProviderKeys(userId: string): Promise<ProviderKey[]>;
30
+ createProviderKey(userId: string, provider: string, encryptedKey: {
31
+ encrypted: string;
32
+ iv: string;
33
+ authTag: string;
34
+ }, keyPrefix: string): Promise<ProviderKey>;
35
+ updateProviderKey(userId: string, provider: string, encryptedKey: {
36
+ encrypted: string;
37
+ iv: string;
38
+ authTag: string;
39
+ }, keyPrefix: string): Promise<ProviderKey | null>;
40
+ deleteProviderKey(userId: string, provider: string): Promise<boolean>;
41
+ hardDeleteProviderKey(userId: string, provider: string): Promise<boolean>;
42
+ getDeletedProviderKeys(daysOld?: number): Promise<ProviderKey[]>;
28
43
  };
29
44
  export default getPool;
30
45
  //# sourceMappingURL=postgres.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/lib/db/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAyB,MAAM,eAAe,CAAC;AAO/E,iBAAS,OAAO,IAAI,EAAE,CAAC,IAAI,CAqB1B;AA0BD,eAAO,MAAM,EAAE;gBAEK,MAAM,WAAW,GAAG,EAAE;0BASZ,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;oBAQnC,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;sBAQ3B,MAAM,gBAAgB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;6BASrC,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;yBAQnC,MAAM,WAAW,MAAM,aAAa,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;kCAQjE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;8BAO1B,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;qBAQnC,MAAM,UAAU,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;iCAS7B,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;+BAQjD,MAAM,UAAU,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;4BAQhD,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;uBAQ7B,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;oBA4BpC,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;mBAQ9B,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;mBA4CxC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;qBASvB,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;iCAgBP,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;6BAQhE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;qCAehB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAM9D,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/lib/db/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAyB,WAAW,EAAE,MAAM,eAAe,CAAC;AAO5F,iBAAS,OAAO,IAAI,EAAE,CAAC,IAAI,CAqB1B;AA0BD,eAAO,MAAM,EAAE;gBAEK,MAAM,WAAW,GAAG,EAAE;0BASZ,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;oBAQnC,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;sBAQ3B,MAAM,gBAAgB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;6BASrC,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;yBAQnC,MAAM,WAAW,MAAM,aAAa,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;kCAQjE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;8BAO1B,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;qBAQnC,MAAM,UAAU,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;iCAS7B,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;+BAQjD,MAAM,UAAU,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;4BAQhD,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;uBAQ7B,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;oBA4BpC,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;mBAQ9B,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;mBA4CxC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;qBASvB,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;iCAgBP,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;6BAQhE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;qCAehB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;2BAQhC,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;4BAQrD,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;8BASnD,MAAM,YACJ,MAAM,gBACF;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,aACrD,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC;8BAWb,MAAM,YACJ,MAAM,gBACF;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,aACrD,MAAM,GAChB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;8BAWE,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;kCAQvC,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;qCAQzC,MAAM,GAAQ,OAAO,CAAC,WAAW,EAAE,CAAC;CAU3E,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -196,6 +196,43 @@ export const db = {
196
196
  },
197
197
  async deleteSessionKeysForUser(userId) {
198
198
  await getPool().query('DELETE FROM session_keys WHERE user_id = $1', [userId]);
199
- }
199
+ },
200
+ // Provider Keys (BYOK)
201
+ async getProviderKey(userId, provider) {
202
+ const result = await getPool().query('SELECT * FROM provider_keys WHERE user_id = $1 AND provider = $2 AND deleted_at IS NULL', [userId, provider]);
203
+ return result.rows[0] ? toCamelCase(result.rows[0]) : null;
204
+ },
205
+ async getProviderKeys(userId) {
206
+ const result = await getPool().query('SELECT * FROM provider_keys WHERE user_id = $1 AND deleted_at IS NULL ORDER BY created_at DESC', [userId]);
207
+ return result.rows.map(toCamelCase);
208
+ },
209
+ async createProviderKey(userId, provider, encryptedKey, keyPrefix) {
210
+ const result = await getPool().query(`INSERT INTO provider_keys (user_id, provider, encrypted_key, key_prefix)
211
+ VALUES ($1, $2, $3, $4)
212
+ RETURNING *`, [userId, provider, JSON.stringify(encryptedKey), keyPrefix]);
213
+ return toCamelCase(result.rows[0]);
214
+ },
215
+ async updateProviderKey(userId, provider, encryptedKey, keyPrefix) {
216
+ const result = await getPool().query(`UPDATE provider_keys
217
+ SET encrypted_key = $3, key_prefix = $4, deleted_at = NULL, updated_at = NOW()
218
+ WHERE user_id = $1 AND provider = $2
219
+ RETURNING *`, [userId, provider, JSON.stringify(encryptedKey), keyPrefix]);
220
+ return result.rows[0] ? toCamelCase(result.rows[0]) : null;
221
+ },
222
+ async deleteProviderKey(userId, provider) {
223
+ const result = await getPool().query('UPDATE provider_keys SET deleted_at = NOW() WHERE user_id = $1 AND provider = $2 AND deleted_at IS NULL', [userId, provider]);
224
+ return (result.rowCount ?? 0) > 0;
225
+ },
226
+ async hardDeleteProviderKey(userId, provider) {
227
+ const result = await getPool().query('DELETE FROM provider_keys WHERE user_id = $1 AND provider = $2', [userId, provider]);
228
+ return (result.rowCount ?? 0) > 0;
229
+ },
230
+ async getDeletedProviderKeys(daysOld = 90) {
231
+ const result = await getPool().query(`SELECT * FROM provider_keys
232
+ WHERE deleted_at IS NOT NULL
233
+ AND deleted_at < NOW() - INTERVAL '1 day' * $1
234
+ ORDER BY deleted_at ASC`, [daysOld]);
235
+ return result.rows.map(toCamelCase);
236
+ },
200
237
  };
201
238
  export default getPool;
@@ -0,0 +1,9 @@
1
+ export interface EncryptedData {
2
+ encrypted: string;
3
+ iv: string;
4
+ authTag: string;
5
+ }
6
+ export declare function encrypt(plaintext: string, masterKey: string): EncryptedData;
7
+ export declare function decrypt(encryptedData: EncryptedData, masterKey: string): string;
8
+ export declare function generateEncryptionKey(): string;
9
+ //# sourceMappingURL=encryption.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/lib/encryption.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,CAqB3E;AAED,wBAAgB,OAAO,CAAC,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAmB/E;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C"}
@@ -0,0 +1,39 @@
1
+ import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
2
+ export function encrypt(plaintext, masterKey) {
3
+ if (!plaintext) {
4
+ throw new Error("Plaintext is required");
5
+ }
6
+ if (!masterKey || masterKey.length !== 64) {
7
+ throw new Error("Master key must be a 64-character hex string (32 bytes)");
8
+ }
9
+ const iv = randomBytes(12);
10
+ const keyBuffer = Buffer.from(masterKey, "hex");
11
+ const cipher = createCipheriv("aes-256-gcm", keyBuffer, iv);
12
+ let encrypted = cipher.update(plaintext, "utf-8", "hex");
13
+ encrypted += cipher.final("hex");
14
+ const authTag = cipher.getAuthTag();
15
+ return {
16
+ encrypted,
17
+ iv: iv.toString("hex"),
18
+ authTag: authTag.toString("hex"),
19
+ };
20
+ }
21
+ export function decrypt(encryptedData, masterKey) {
22
+ if (!encryptedData || !encryptedData.encrypted || !encryptedData.iv || !encryptedData.authTag) {
23
+ throw new Error("Invalid encrypted data structure");
24
+ }
25
+ if (!masterKey || masterKey.length !== 64) {
26
+ throw new Error("Master key must be a 64-character hex string (32 bytes)");
27
+ }
28
+ const keyBuffer = Buffer.from(masterKey, "hex");
29
+ const ivBuffer = Buffer.from(encryptedData.iv, "hex");
30
+ const authTagBuffer = Buffer.from(encryptedData.authTag, "hex");
31
+ const decipher = createDecipheriv("aes-256-gcm", keyBuffer, ivBuffer);
32
+ decipher.setAuthTag(authTagBuffer);
33
+ let decrypted = decipher.update(encryptedData.encrypted, "hex", "utf8");
34
+ decrypted += decipher.final("utf8");
35
+ return decrypted;
36
+ }
37
+ export function generateEncryptionKey() {
38
+ return randomBytes(32).toString("hex");
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@layer-ai/core",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "Core API routes and services for Layer AI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -36,7 +36,7 @@
36
36
  "nanoid": "^5.0.4",
37
37
  "openai": "^4.24.0",
38
38
  "pg": "^8.11.3",
39
- "@layer-ai/sdk": "^0.6.0"
39
+ "@layer-ai/sdk": "^0.7.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/bcryptjs": "^2.4.6",