@opentrust/db 7.1.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/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +51 -0
- package/dist/dialect.d.ts +3 -0
- package/dist/dialect.d.ts.map +1 -0
- package/dist/dialect.js +12 -0
- package/dist/generate.d.ts +2 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +20 -0
- package/dist/helpers.d.ts +11 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +32 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/migrate.d.ts +2 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +61 -0
- package/dist/queries/agents.d.ts +25 -0
- package/dist/queries/agents.d.ts.map +1 -0
- package/dist/queries/agents.js +46 -0
- package/dist/queries/auth.d.ts +18 -0
- package/dist/queries/auth.d.ts.map +1 -0
- package/dist/queries/auth.js +77 -0
- package/dist/queries/detection-results.d.ts +24 -0
- package/dist/queries/detection-results.d.ts.map +1 -0
- package/dist/queries/detection-results.js +43 -0
- package/dist/queries/observations.d.ts +58 -0
- package/dist/queries/observations.d.ts.map +1 -0
- package/dist/queries/observations.js +212 -0
- package/dist/queries/policies.d.ts +25 -0
- package/dist/queries/policies.d.ts.map +1 -0
- package/dist/queries/policies.js +38 -0
- package/dist/queries/scanners.d.ts +25 -0
- package/dist/queries/scanners.d.ts.map +1 -0
- package/dist/queries/scanners.js +56 -0
- package/dist/queries/settings.d.ts +8 -0
- package/dist/queries/settings.d.ts.map +1 -0
- package/dist/queries/settings.js +30 -0
- package/dist/queries/usage.d.ts +18 -0
- package/dist/queries/usage.d.ts.map +1 -0
- package/dist/queries/usage.js +54 -0
- package/dist/schema/index.d.ts +4415 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +19 -0
- package/dist/schema/mysql.d.ts +1479 -0
- package/dist/schema/mysql.d.ts.map +1 -0
- package/dist/schema/mysql.js +151 -0
- package/dist/schema/pg.d.ts +1479 -0
- package/dist/schema/pg.d.ts.map +1 -0
- package/dist/schema/pg.js +151 -0
- package/dist/schema/sqlite.d.ts +1479 -0
- package/dist/schema/sqlite.d.ts.map +1 -0
- package/dist/schema/sqlite.js +153 -0
- package/dist/seed.d.ts +2 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +49 -0
- package/drizzle/sqlite/0000_serious_martin_li.sql +143 -0
- package/drizzle/sqlite/meta/0000_snapshot.json +945 -0
- package/drizzle/sqlite/meta/_journal.json +13 -0
- package/drizzle.config.mysql.ts +10 -0
- package/drizzle.config.pg.ts +10 -0
- package/drizzle.config.sqlite.ts +10 -0
- package/package.json +55 -0
- package/src/client.ts +66 -0
- package/src/dialect.ts +13 -0
- package/src/generate.ts +26 -0
- package/src/helpers.ts +47 -0
- package/src/index.ts +12 -0
- package/src/migrate.ts +74 -0
- package/src/queries/agents.ts +68 -0
- package/src/queries/auth.ts +94 -0
- package/src/queries/detection-results.ts +58 -0
- package/src/queries/observations.ts +275 -0
- package/src/queries/policies.ts +59 -0
- package/src/queries/scanners.ts +74 -0
- package/src/queries/settings.ts +34 -0
- package/src/queries/usage.ts +69 -0
- package/src/schema/index.ts +22 -0
- package/src/schema/mysql.ts +207 -0
- package/src/schema/pg.ts +208 -0
- package/src/schema/sqlite.ts +199 -0
- package/src/seed.ts +56 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAgEA,eAAO,MAAM,EAAE,EAAE,GAAsB,CAAC;AACxC,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { config } from "dotenv";
|
|
2
|
+
import { resolve, dirname, join } from "path";
|
|
3
|
+
import { mkdirSync, existsSync } from "fs";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { getDialect } from "./dialect.js";
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
// Load .env from project root if DATABASE_URL is not already set
|
|
9
|
+
if (!process.env.DATABASE_URL && !process.env.DB_DIALECT) {
|
|
10
|
+
config({ path: resolve(__dirname, "../../../.env") });
|
|
11
|
+
}
|
|
12
|
+
const dialect = getDialect();
|
|
13
|
+
// Database path configuration:
|
|
14
|
+
// - DASHBOARD_DATA_DIR: directory for data files (default: dashboard/data)
|
|
15
|
+
// - DATABASE_URL: full path to SQLite file (overrides DASHBOARD_DATA_DIR for SQLite)
|
|
16
|
+
function getDefaultDbPath() {
|
|
17
|
+
const dataDir = process.env.DASHBOARD_DATA_DIR || resolve(__dirname, "../../../data");
|
|
18
|
+
return join(dataDir, "dashboard.db");
|
|
19
|
+
}
|
|
20
|
+
async function createDb() {
|
|
21
|
+
if (dialect === "sqlite") {
|
|
22
|
+
const { default: Database } = await import("better-sqlite3");
|
|
23
|
+
const { drizzle } = await import("drizzle-orm/better-sqlite3");
|
|
24
|
+
const schema = await import("./schema/sqlite.js");
|
|
25
|
+
const rawUrl = process.env.DATABASE_URL || getDefaultDbPath();
|
|
26
|
+
const dbPath = rawUrl.replace(/^file:/, "");
|
|
27
|
+
// Ensure directory exists
|
|
28
|
+
const dir = dirname(dbPath);
|
|
29
|
+
if (!existsSync(dir)) {
|
|
30
|
+
mkdirSync(dir, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
const sqlite = new Database(dbPath);
|
|
33
|
+
sqlite.pragma("journal_mode = WAL");
|
|
34
|
+
sqlite.pragma("foreign_keys = ON");
|
|
35
|
+
return drizzle(sqlite, { schema });
|
|
36
|
+
}
|
|
37
|
+
if (dialect === "mysql") {
|
|
38
|
+
const mysql2 = await import("mysql2/promise");
|
|
39
|
+
const { drizzle } = await import("drizzle-orm/mysql2");
|
|
40
|
+
const schema = await import("./schema/mysql.js");
|
|
41
|
+
const pool = mysql2.createPool(process.env.DATABASE_URL);
|
|
42
|
+
return drizzle(pool, { schema, mode: "default" });
|
|
43
|
+
}
|
|
44
|
+
// postgresql (default)
|
|
45
|
+
const pg = await import("postgres");
|
|
46
|
+
const { drizzle } = await import("drizzle-orm/postgres-js");
|
|
47
|
+
const schema = await import("./schema/pg.js");
|
|
48
|
+
const queryClient = pg.default(process.env.DATABASE_URL);
|
|
49
|
+
return drizzle(queryClient, { schema });
|
|
50
|
+
}
|
|
51
|
+
export const db = await createDb();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../src/dialect.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;AAExD,wBAAgB,UAAU,IAAI,OAAO,CAUpC"}
|
package/dist/dialect.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function getDialect() {
|
|
2
|
+
const explicit = process.env.DB_DIALECT;
|
|
3
|
+
if (explicit === "sqlite" || explicit === "mysql" || explicit === "postgresql") {
|
|
4
|
+
return explicit;
|
|
5
|
+
}
|
|
6
|
+
const url = process.env.DATABASE_URL || "";
|
|
7
|
+
if (url.startsWith("mysql://") || url.startsWith("mysql2://"))
|
|
8
|
+
return "mysql";
|
|
9
|
+
if (url.startsWith("postgres://") || url.startsWith("postgresql://"))
|
|
10
|
+
return "postgresql";
|
|
11
|
+
return "sqlite";
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":""}
|
package/dist/generate.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { config } from "dotenv";
|
|
2
|
+
import { resolve, dirname } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
config({ path: resolve(__dirname, "../../../.env") });
|
|
8
|
+
const { getDialect } = await import("./dialect.js");
|
|
9
|
+
const dialect = getDialect();
|
|
10
|
+
const configMap = {
|
|
11
|
+
sqlite: "drizzle.config.sqlite.ts",
|
|
12
|
+
mysql: "drizzle.config.mysql.ts",
|
|
13
|
+
postgresql: "drizzle.config.pg.ts",
|
|
14
|
+
};
|
|
15
|
+
const configFile = configMap[dialect];
|
|
16
|
+
console.log(`Generating migrations for dialect: ${dialect}`);
|
|
17
|
+
execSync(`npx drizzle-kit generate --config=${configFile}`, {
|
|
18
|
+
cwd: resolve(__dirname, ".."),
|
|
19
|
+
stdio: "inherit",
|
|
20
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-dialect insert with returning.
|
|
3
|
+
* PostgreSQL and SQLite support .returning(), MySQL does not.
|
|
4
|
+
* All dialects generate UUID client-side for predictability.
|
|
5
|
+
*/
|
|
6
|
+
export declare function insertReturning<T>(db: any, table: any, values: Record<string, unknown>): Promise<T>;
|
|
7
|
+
/**
|
|
8
|
+
* Cross-dialect update with returning.
|
|
9
|
+
*/
|
|
10
|
+
export declare function updateReturning<T>(db: any, table: any, where: any, values: Record<string, unknown>): Promise<T | null>;
|
|
11
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,EAAE,EAAE,GAAG,EACP,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,CAAC,CAAC,CAaZ;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,EAAE,EAAE,GAAG,EACP,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAWnB"}
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
import { getDialect } from "./dialect.js";
|
|
3
|
+
/**
|
|
4
|
+
* Cross-dialect insert with returning.
|
|
5
|
+
* PostgreSQL and SQLite support .returning(), MySQL does not.
|
|
6
|
+
* All dialects generate UUID client-side for predictability.
|
|
7
|
+
*/
|
|
8
|
+
export async function insertReturning(db, table, values) {
|
|
9
|
+
const dialect = getDialect();
|
|
10
|
+
const id = crypto.randomUUID();
|
|
11
|
+
const row = { ...values, id };
|
|
12
|
+
if (dialect === "mysql") {
|
|
13
|
+
await db.insert(table).values(row);
|
|
14
|
+
const result = await db.select().from(table).where(eq(table.id, id)).limit(1);
|
|
15
|
+
return result[0];
|
|
16
|
+
}
|
|
17
|
+
const result = await db.insert(table).values(row).returning();
|
|
18
|
+
return result[0];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Cross-dialect update with returning.
|
|
22
|
+
*/
|
|
23
|
+
export async function updateReturning(db, table, where, values) {
|
|
24
|
+
const dialect = getDialect();
|
|
25
|
+
if (dialect === "mysql") {
|
|
26
|
+
await db.update(table).set(values).where(where);
|
|
27
|
+
const result = await db.select().from(table).where(where).limit(1);
|
|
28
|
+
return result[0] ?? null;
|
|
29
|
+
}
|
|
30
|
+
const result = await db.update(table).set(values).where(where).returning();
|
|
31
|
+
return result[0] ?? null;
|
|
32
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { db, type Database } from "./client.js";
|
|
2
|
+
export { getDialect, type Dialect } from "./dialect.js";
|
|
3
|
+
export * from "./schema/index.js";
|
|
4
|
+
export { insertReturning, updateReturning } from "./helpers.js";
|
|
5
|
+
export { agentQueries } from "./queries/agents.js";
|
|
6
|
+
export { scannerQueries } from "./queries/scanners.js";
|
|
7
|
+
export { policyQueries } from "./queries/policies.js";
|
|
8
|
+
export { usageQueries } from "./queries/usage.js";
|
|
9
|
+
export { detectionResultQueries } from "./queries/detection-results.js";
|
|
10
|
+
export { settingsQueries } from "./queries/settings.js";
|
|
11
|
+
export { observationQueries, inferCategory, inferAccessPattern } from "./queries/observations.js";
|
|
12
|
+
export { authQueries } from "./queries/auth.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AACxD,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { db } from "./client.js";
|
|
2
|
+
export { getDialect } from "./dialect.js";
|
|
3
|
+
export * from "./schema/index.js";
|
|
4
|
+
export { insertReturning, updateReturning } from "./helpers.js";
|
|
5
|
+
export { agentQueries } from "./queries/agents.js";
|
|
6
|
+
export { scannerQueries } from "./queries/scanners.js";
|
|
7
|
+
export { policyQueries } from "./queries/policies.js";
|
|
8
|
+
export { usageQueries } from "./queries/usage.js";
|
|
9
|
+
export { detectionResultQueries } from "./queries/detection-results.js";
|
|
10
|
+
export { settingsQueries } from "./queries/settings.js";
|
|
11
|
+
export { observationQueries, inferCategory, inferAccessPattern } from "./queries/observations.js";
|
|
12
|
+
export { authQueries } from "./queries/auth.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":""}
|
package/dist/migrate.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { config } from "dotenv";
|
|
2
|
+
import { resolve, dirname, join } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = dirname(__filename);
|
|
6
|
+
config({ path: resolve(__dirname, "../../../.env") });
|
|
7
|
+
// Database path configuration:
|
|
8
|
+
// - DASHBOARD_DATA_DIR: directory for data files (default: dashboard/data)
|
|
9
|
+
// - DATABASE_URL: full path to SQLite file (overrides DASHBOARD_DATA_DIR for SQLite)
|
|
10
|
+
function getDefaultDbPath() {
|
|
11
|
+
const dataDir = process.env.DASHBOARD_DATA_DIR || resolve(__dirname, "../../../data");
|
|
12
|
+
return join(dataDir, "dashboard.db");
|
|
13
|
+
}
|
|
14
|
+
async function runMigrations() {
|
|
15
|
+
const { getDialect } = await import("./dialect.js");
|
|
16
|
+
const dialect = getDialect();
|
|
17
|
+
console.log(`Running migrations for dialect: ${dialect}`);
|
|
18
|
+
if (dialect === "sqlite") {
|
|
19
|
+
const { default: Database } = await import("better-sqlite3");
|
|
20
|
+
const { drizzle } = await import("drizzle-orm/better-sqlite3");
|
|
21
|
+
const { migrate } = await import("drizzle-orm/better-sqlite3/migrator");
|
|
22
|
+
const { mkdirSync, existsSync } = await import("fs");
|
|
23
|
+
const { dirname } = await import("path");
|
|
24
|
+
const rawUrl = process.env.DATABASE_URL || getDefaultDbPath();
|
|
25
|
+
const dbPath = rawUrl.replace(/^file:/, "");
|
|
26
|
+
const dir = dirname(dbPath);
|
|
27
|
+
if (!existsSync(dir))
|
|
28
|
+
mkdirSync(dir, { recursive: true });
|
|
29
|
+
const sqlite = new Database(dbPath);
|
|
30
|
+
sqlite.pragma("journal_mode = WAL");
|
|
31
|
+
const db = drizzle(sqlite);
|
|
32
|
+
migrate(db, { migrationsFolder: resolve(__dirname, "../drizzle/sqlite") });
|
|
33
|
+
console.log("SQLite migrations complete.");
|
|
34
|
+
sqlite.close();
|
|
35
|
+
}
|
|
36
|
+
else if (dialect === "mysql") {
|
|
37
|
+
const mysql2 = await import("mysql2/promise");
|
|
38
|
+
const { drizzle } = await import("drizzle-orm/mysql2");
|
|
39
|
+
const { migrate } = await import("drizzle-orm/mysql2/migrator");
|
|
40
|
+
const pool = mysql2.createPool(process.env.DATABASE_URL);
|
|
41
|
+
const db = drizzle(pool);
|
|
42
|
+
await migrate(db, { migrationsFolder: resolve(__dirname, "../drizzle/mysql") });
|
|
43
|
+
console.log("MySQL migrations complete.");
|
|
44
|
+
await pool.end();
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const pg = await import("postgres");
|
|
48
|
+
const { drizzle } = await import("drizzle-orm/postgres-js");
|
|
49
|
+
const { migrate } = await import("drizzle-orm/postgres-js/migrator");
|
|
50
|
+
const queryClient = pg.default(process.env.DATABASE_URL, { max: 1 });
|
|
51
|
+
const db = drizzle(queryClient);
|
|
52
|
+
await migrate(db, { migrationsFolder: resolve(__dirname, "../drizzle/postgresql") });
|
|
53
|
+
console.log("PostgreSQL migrations complete.");
|
|
54
|
+
await queryClient.end();
|
|
55
|
+
}
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
58
|
+
runMigrations().catch((err) => {
|
|
59
|
+
console.error("Migration failed:", err);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Database } from "../client.js";
|
|
2
|
+
export declare function agentQueries(db: Database): {
|
|
3
|
+
findById(id: string, tenantId?: string): Promise<any>;
|
|
4
|
+
findByName(name: string, tenantId?: string): Promise<any>;
|
|
5
|
+
findAll(tenantId?: string): Promise<any>;
|
|
6
|
+
countAll(tenantId?: string): Promise<any>;
|
|
7
|
+
create(data: {
|
|
8
|
+
name: string;
|
|
9
|
+
description?: string | null;
|
|
10
|
+
provider?: string;
|
|
11
|
+
metadata?: Record<string, unknown>;
|
|
12
|
+
tenantId?: string;
|
|
13
|
+
}): Promise<unknown>;
|
|
14
|
+
update(id: string, data: Partial<{
|
|
15
|
+
name: string;
|
|
16
|
+
description: string | null;
|
|
17
|
+
provider: string;
|
|
18
|
+
status: string;
|
|
19
|
+
lastSeenAt: Date | string;
|
|
20
|
+
metadata: Record<string, unknown>;
|
|
21
|
+
}>, tenantId?: string): Promise<unknown>;
|
|
22
|
+
delete(id: string, tenantId?: string): Promise<void>;
|
|
23
|
+
heartbeat(id: string, tenantId?: string): Promise<void>;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=agents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/queries/agents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAK7C,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ;iBAElB,MAAM,aAAY,MAAM;qBAKpB,MAAM,aAAY,MAAM;uBAKvB,MAAM;wBAIL,MAAM;iBAKZ;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;eASgB,MAAM,QAAQ,OAAO,CAAC;QACrC,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC;QAC1B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,CAAC,aAAY,MAAM;eAOH,MAAM,aAAY,MAAM;kBAIrB,MAAM,aAAY,MAAM;EAO/C"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { eq, and, count } from "drizzle-orm";
|
|
2
|
+
import { agents } from "../schema/index.js";
|
|
3
|
+
import { insertReturning, updateReturning } from "../helpers.js";
|
|
4
|
+
import { DEFAULT_TENANT_ID } from "@opentrust/shared";
|
|
5
|
+
export function agentQueries(db) {
|
|
6
|
+
return {
|
|
7
|
+
async findById(id, tenantId = DEFAULT_TENANT_ID) {
|
|
8
|
+
const result = await db.select().from(agents).where(and(eq(agents.id, id), eq(agents.tenantId, tenantId))).limit(1);
|
|
9
|
+
return result[0] ?? null;
|
|
10
|
+
},
|
|
11
|
+
async findByName(name, tenantId = DEFAULT_TENANT_ID) {
|
|
12
|
+
const result = await db.select().from(agents).where(and(eq(agents.name, name), eq(agents.tenantId, tenantId))).limit(1);
|
|
13
|
+
return result[0] ?? null;
|
|
14
|
+
},
|
|
15
|
+
async findAll(tenantId = DEFAULT_TENANT_ID) {
|
|
16
|
+
return db.select().from(agents).where(eq(agents.tenantId, tenantId)).orderBy(agents.createdAt);
|
|
17
|
+
},
|
|
18
|
+
async countAll(tenantId = DEFAULT_TENANT_ID) {
|
|
19
|
+
const result = await db.select({ count: count() }).from(agents).where(eq(agents.tenantId, tenantId));
|
|
20
|
+
return result[0]?.count ?? 0;
|
|
21
|
+
},
|
|
22
|
+
async create(data) {
|
|
23
|
+
return insertReturning(db, agents, {
|
|
24
|
+
...data,
|
|
25
|
+
provider: data.provider ?? "custom",
|
|
26
|
+
metadata: data.metadata ?? {},
|
|
27
|
+
tenantId: data.tenantId ?? DEFAULT_TENANT_ID,
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
async update(id, data, tenantId = DEFAULT_TENANT_ID) {
|
|
31
|
+
return updateReturning(db, agents, and(eq(agents.id, id), eq(agents.tenantId, tenantId)), {
|
|
32
|
+
...data,
|
|
33
|
+
updatedAt: new Date().toISOString(),
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
async delete(id, tenantId = DEFAULT_TENANT_ID) {
|
|
37
|
+
await db.delete(agents).where(and(eq(agents.id, id), eq(agents.tenantId, tenantId)));
|
|
38
|
+
},
|
|
39
|
+
async heartbeat(id, tenantId = DEFAULT_TENANT_ID) {
|
|
40
|
+
await db
|
|
41
|
+
.update(agents)
|
|
42
|
+
.set({ status: "active", lastSeenAt: new Date().toISOString(), updatedAt: new Date().toISOString() })
|
|
43
|
+
.where(and(eq(agents.id, id), eq(agents.tenantId, tenantId)));
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Database } from "../client.js";
|
|
2
|
+
import { magicLinks, userSessions } from "../schema/index.js";
|
|
3
|
+
export declare function authQueries(db: Database): {
|
|
4
|
+
createMagicLink(email: string, token: string, expiresAt: string): any;
|
|
5
|
+
/** Returns the magic link only if valid (not used, not expired) */
|
|
6
|
+
findValidMagicLink(token: string): typeof magicLinks.$inferSelect | undefined;
|
|
7
|
+
/** Fetch by token regardless of status (for validation logic in route) */
|
|
8
|
+
findMagicLink(token: string): typeof magicLinks.$inferSelect | undefined;
|
|
9
|
+
markMagicLinkUsed(id: string): any;
|
|
10
|
+
/** Delete expired and used magic links (housekeeping) */
|
|
11
|
+
pruneExpiredMagicLinks(): any;
|
|
12
|
+
createSession(email: string, token: string, expiresAt: string): any;
|
|
13
|
+
findSession(token: string): typeof userSessions.$inferSelect | undefined;
|
|
14
|
+
deleteSession(token: string): any;
|
|
15
|
+
/** Delete expired sessions (housekeeping) */
|
|
16
|
+
pruneExpiredSessions(): any;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/queries/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE9D,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ;2BAIb,MAAM,SAAS,MAAM,aAAa,MAAM;IAQ/D,mEAAmE;8BACzC,MAAM,GAalB,OAAO,UAAU,CAAC,YAAY,GAAG,SAAS;IAGxD,0EAA0E;yBACrD,MAAM,GAKb,OAAO,UAAU,CAAC,YAAY,GAAG,SAAS;0BAGlC,MAAM;IAQ5B,yDAAyD;;yBAWpC,MAAM,SAAS,MAAM,aAAa,MAAM;uBAQ1C,MAAM,GAKX,OAAO,YAAY,CAAC,YAAY,GAAG,SAAS;yBAGrC,MAAM;IAO3B,6CAA6C;;EAShD"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { eq, lt, and, isNull } from "drizzle-orm";
|
|
2
|
+
import { magicLinks, userSessions } from "../schema/index.js";
|
|
3
|
+
export function authQueries(db) {
|
|
4
|
+
return {
|
|
5
|
+
// ── Magic Links ──────────────────────────────────────────────
|
|
6
|
+
createMagicLink(email, token, expiresAt) {
|
|
7
|
+
return db
|
|
8
|
+
.insert(magicLinks)
|
|
9
|
+
.values({ email, token, expiresAt })
|
|
10
|
+
.returning()
|
|
11
|
+
.get();
|
|
12
|
+
},
|
|
13
|
+
/** Returns the magic link only if valid (not used, not expired) */
|
|
14
|
+
findValidMagicLink(token) {
|
|
15
|
+
const now = new Date().toISOString();
|
|
16
|
+
return db
|
|
17
|
+
.select()
|
|
18
|
+
.from(magicLinks)
|
|
19
|
+
.where(and(eq(magicLinks.token, token), isNull(magicLinks.usedAt),
|
|
20
|
+
// expiresAt > now (string comparison works for ISO 8601)
|
|
21
|
+
lt(magicLinks.createdAt, magicLinks.expiresAt)))
|
|
22
|
+
.get();
|
|
23
|
+
},
|
|
24
|
+
/** Fetch by token regardless of status (for validation logic in route) */
|
|
25
|
+
findMagicLink(token) {
|
|
26
|
+
return db
|
|
27
|
+
.select()
|
|
28
|
+
.from(magicLinks)
|
|
29
|
+
.where(eq(magicLinks.token, token))
|
|
30
|
+
.get();
|
|
31
|
+
},
|
|
32
|
+
markMagicLinkUsed(id) {
|
|
33
|
+
return db
|
|
34
|
+
.update(magicLinks)
|
|
35
|
+
.set({ usedAt: new Date().toISOString() })
|
|
36
|
+
.where(eq(magicLinks.id, id))
|
|
37
|
+
.run();
|
|
38
|
+
},
|
|
39
|
+
/** Delete expired and used magic links (housekeeping) */
|
|
40
|
+
pruneExpiredMagicLinks() {
|
|
41
|
+
const now = new Date().toISOString();
|
|
42
|
+
return db
|
|
43
|
+
.delete(magicLinks)
|
|
44
|
+
.where(lt(magicLinks.expiresAt, now))
|
|
45
|
+
.run();
|
|
46
|
+
},
|
|
47
|
+
// ── User Sessions ────────────────────────────────────────────
|
|
48
|
+
createSession(email, token, expiresAt) {
|
|
49
|
+
return db
|
|
50
|
+
.insert(userSessions)
|
|
51
|
+
.values({ email, token, expiresAt })
|
|
52
|
+
.returning()
|
|
53
|
+
.get();
|
|
54
|
+
},
|
|
55
|
+
findSession(token) {
|
|
56
|
+
return db
|
|
57
|
+
.select()
|
|
58
|
+
.from(userSessions)
|
|
59
|
+
.where(eq(userSessions.token, token))
|
|
60
|
+
.get();
|
|
61
|
+
},
|
|
62
|
+
deleteSession(token) {
|
|
63
|
+
return db
|
|
64
|
+
.delete(userSessions)
|
|
65
|
+
.where(eq(userSessions.token, token))
|
|
66
|
+
.run();
|
|
67
|
+
},
|
|
68
|
+
/** Delete expired sessions (housekeeping) */
|
|
69
|
+
pruneExpiredSessions() {
|
|
70
|
+
const now = new Date().toISOString();
|
|
71
|
+
return db
|
|
72
|
+
.delete(userSessions)
|
|
73
|
+
.where(lt(userSessions.expiresAt, now))
|
|
74
|
+
.run();
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Database } from "../client.js";
|
|
2
|
+
export declare function detectionResultQueries(db: Database): {
|
|
3
|
+
create(data: {
|
|
4
|
+
agentId?: string | null;
|
|
5
|
+
safe: boolean;
|
|
6
|
+
categories: string[];
|
|
7
|
+
sensitivityScore: number;
|
|
8
|
+
findings: unknown[];
|
|
9
|
+
latencyMs: number;
|
|
10
|
+
requestId: string;
|
|
11
|
+
tenantId?: string;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
findAll(options?: {
|
|
14
|
+
limit?: number;
|
|
15
|
+
offset?: number;
|
|
16
|
+
tenantId?: string;
|
|
17
|
+
}): Promise<any>;
|
|
18
|
+
findByAgentId(agentId: string, options?: {
|
|
19
|
+
limit?: number;
|
|
20
|
+
offset?: number;
|
|
21
|
+
tenantId?: string;
|
|
22
|
+
}): Promise<any>;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=detection-results.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detection-results.d.ts","sourceRoot":"","sources":["../../src/queries/detection-results.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI7C,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ;iBAE5B;QACjB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,IAAI,EAAE,OAAO,CAAC;QACd,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;sBAOuB;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;2BAiBjD,MAAM,YAAY;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;EAiBxG"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { eq, and, desc } from "drizzle-orm";
|
|
2
|
+
import { detectionResults } from "../schema/index.js";
|
|
3
|
+
import { DEFAULT_TENANT_ID } from "@opentrust/shared";
|
|
4
|
+
export function detectionResultQueries(db) {
|
|
5
|
+
return {
|
|
6
|
+
async create(data) {
|
|
7
|
+
await db.insert(detectionResults).values({
|
|
8
|
+
...data,
|
|
9
|
+
tenantId: data.tenantId ?? DEFAULT_TENANT_ID,
|
|
10
|
+
});
|
|
11
|
+
},
|
|
12
|
+
async findAll(options) {
|
|
13
|
+
const tenantId = options?.tenantId ?? DEFAULT_TENANT_ID;
|
|
14
|
+
let query = db
|
|
15
|
+
.select()
|
|
16
|
+
.from(detectionResults)
|
|
17
|
+
.where(eq(detectionResults.tenantId, tenantId))
|
|
18
|
+
.orderBy(desc(detectionResults.createdAt));
|
|
19
|
+
if (options?.limit) {
|
|
20
|
+
query = query.limit(options.limit);
|
|
21
|
+
}
|
|
22
|
+
if (options?.offset) {
|
|
23
|
+
query = query.offset(options.offset);
|
|
24
|
+
}
|
|
25
|
+
return query;
|
|
26
|
+
},
|
|
27
|
+
async findByAgentId(agentId, options) {
|
|
28
|
+
const tenantId = options?.tenantId ?? DEFAULT_TENANT_ID;
|
|
29
|
+
let query = db
|
|
30
|
+
.select()
|
|
31
|
+
.from(detectionResults)
|
|
32
|
+
.where(and(eq(detectionResults.agentId, agentId), eq(detectionResults.tenantId, tenantId)))
|
|
33
|
+
.orderBy(desc(detectionResults.createdAt));
|
|
34
|
+
if (options?.limit) {
|
|
35
|
+
query = query.limit(options.limit);
|
|
36
|
+
}
|
|
37
|
+
if (options?.offset) {
|
|
38
|
+
query = query.offset(options.offset);
|
|
39
|
+
}
|
|
40
|
+
return query;
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Database } from "../client.js";
|
|
2
|
+
export declare function inferCategory(toolName: string): string;
|
|
3
|
+
export declare function inferAccessPattern(toolName: string): "read" | "write" | "admin" | "unknown";
|
|
4
|
+
export declare function observationQueries(db: Database): {
|
|
5
|
+
/**
|
|
6
|
+
* Record a tool call observation.
|
|
7
|
+
*/
|
|
8
|
+
record(data: {
|
|
9
|
+
agentId: string;
|
|
10
|
+
sessionKey?: string;
|
|
11
|
+
toolName: string;
|
|
12
|
+
params?: Record<string, unknown>;
|
|
13
|
+
phase: "before" | "after";
|
|
14
|
+
result?: unknown;
|
|
15
|
+
error?: string;
|
|
16
|
+
durationMs?: number;
|
|
17
|
+
blocked?: boolean;
|
|
18
|
+
blockReason?: string;
|
|
19
|
+
tenantId?: string;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Upsert an agent permission entry based on observed tool call.
|
|
23
|
+
*/
|
|
24
|
+
upsertPermission(data: {
|
|
25
|
+
agentId: string;
|
|
26
|
+
toolName: string;
|
|
27
|
+
category: string;
|
|
28
|
+
accessPattern: string;
|
|
29
|
+
params?: Record<string, unknown>;
|
|
30
|
+
hasError: boolean;
|
|
31
|
+
tenantId: string;
|
|
32
|
+
}): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Get recent observations, optionally filtered by agentId.
|
|
35
|
+
*/
|
|
36
|
+
findRecent(opts?: {
|
|
37
|
+
agentId?: string;
|
|
38
|
+
limit?: number;
|
|
39
|
+
tenantId?: string;
|
|
40
|
+
}): Promise<any>;
|
|
41
|
+
/**
|
|
42
|
+
* Get the aggregated permission profile for an agent.
|
|
43
|
+
*/
|
|
44
|
+
getPermissions(agentId: string, tenantId?: string): Promise<any>;
|
|
45
|
+
/**
|
|
46
|
+
* Get permissions for all agents (overview).
|
|
47
|
+
*/
|
|
48
|
+
getAllPermissions(tenantId?: string): Promise<any>;
|
|
49
|
+
/**
|
|
50
|
+
* Find first-seen tool calls (anomalies) — permissions with callCount = 1.
|
|
51
|
+
*/
|
|
52
|
+
findAnomalies(tenantId?: string, limit?: number): Promise<any>;
|
|
53
|
+
/**
|
|
54
|
+
* Get observation count summary per agent.
|
|
55
|
+
*/
|
|
56
|
+
summary(tenantId?: string): Promise<any>;
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=observations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observations.d.ts","sourceRoot":"","sources":["../../src/queries/observations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAU7C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkBtD;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAiB3F;AAID,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ;IAE3C;;OAEG;iBACgB;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;QAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;IAmCD;;OAEG;2BAC0B;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB;IAgDD;;OAEG;sBACoB;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;IAiBD;;OAEG;4BAC2B,MAAM,aAAY,MAAM;IAatD;;OAEG;iCAC+B,MAAM;IAQxC;;OAEG;6BAC2B,MAAM,UAA6B,MAAM;IAcvE;;OAEG;uBACqB,MAAM;EAajC"}
|