History

refactor(v2): integrate drizzle-kit for database operations and remove legacy SQL schema

- Added drizzle-kit for database generation and migration scripts in package.json. - Introduced new database operations and removed outdated SQL schema files. - Updated end-to-end tests to accommodate changes in database handling and state management.

Rhys Sullivan committed 8 months ago

Commit 41edbe81 parent 616093c25 files · +5296 −1208Browse files

Unified · Split

25 files
  1. apps/pm/src/approval-runtime.e2e.test.ts +336 −0
  2. apps/pm/src/execute.e2e.test.ts +17 −2
  3. bun.lock +117 −0
  4. packages/persistence-sql/drizzle.config.pg.ts +14 −0
  5. packages/persistence-sql/drizzle.config.ts +12 −0
  6. packages/persistence-sql/drizzle/0000_initial_schema.sql +0 −139
  7. packages/persistence-sql/drizzle/meta/_journal.json +0 −13
  8. packages/persistence-sql/drizzle/postgres/0000_spicy_barracuda.sql +224 −0
  9. packages/persistence-sql/drizzle/postgres/meta/0000_snapshot.json +1509 −0
  10. packages/persistence-sql/drizzle/postgres/meta/_journal.json +13 −0
  11. packages/persistence-sql/drizzle/sqlite/0000_curved_raider.sql +224 −0
  12. packages/persistence-sql/drizzle/sqlite/meta/0000_snapshot.json +1437 −0
  13. packages/persistence-sql/drizzle/sqlite/meta/_journal.json +13 −0
  14. packages/persistence-sql/package.json +11 −1
  15. packages/persistence-sql/src/persistence-codecs.ts +0 −52
  16. packages/persistence-sql/src/row-operations-auth.ts +199 −92
  17. packages/persistence-sql/src/row-operations-core.ts +252 −125
  18. packages/persistence-sql/src/rows-effect-api-auth.ts +116 −0
  19. packages/persistence-sql/src/rows-effect-api-core.ts +157 −0
  20. packages/persistence-sql/src/rows-effect-api.ts +5 −296
  21. packages/persistence-sql/src/rows-effect-helpers.ts +55 −0
  22. packages/persistence-sql/src/schema-pg.ts +304 −0
  23. packages/persistence-sql/src/schema.ts +212 −42
  24. packages/persistence-sql/src/source-artifact-stores.ts +69 −28
  25. packages/persistence-sql/src/sql-internals.ts +0 −418
apps/pm/src/approval-runtime.e2e.test.ts+336−0
@@ -0,0 +1,336 @@
1+import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
2+import { mkdtemp, rm } from "node:fs/promises";
3+import { tmpdir } from "node:os";
4+import * as path from "node:path";
5+
6+import {
7+ HttpApi,
8+ HttpApiEndpoint,
9+ HttpApiGroup,
10+ HttpApiSchema,
11+ OpenApi,
12+} from "@effect/platform";
13+import { describe, expect, it } from "@effect/vitest";
14+import { makeSourceManagerService } from "@executor-v2/management-api";
15+import {
16+ createRunExecutor,
17+ createSourceToolRegistry,
18+ makeOpenApiToolProvider,
19+ makeRuntimeAdapterRegistry,
20+ makeToolProviderRegistry,
21+} from "@executor-v2/engine";
22+import { makeSqlControlPlanePersistence } from "@executor-v2/persistence-sql";
23+import { SourceSchema, type Source } from "@executor-v2/schema";
24+import { makeLocalInProcessRuntimeAdapter } from "@executor-v2/runtime-local-inproc";
25+import * as Effect from "effect/Effect";
26+import * as Schema from "effect/Schema";
27+
28+import {
29+ createPmApprovalsService,
30+ createPmPersistentToolApprovalPolicy,
31+} from "./approvals-service";
32+import { createPmExecuteRuntimeRun } from "./runtime-execution-port";
33+
34+type TestServer = {
35+ baseUrl: string;
36+ requests: Array<string>;
37+ close: () => Promise<void>;
38+};
39+
40+const decodeSource = Schema.decodeUnknownSync(SourceSchema);
41+
42+const githubOwnerParam = HttpApiSchema.param("owner", Schema.String);
43+const githubRepoParam = HttpApiSchema.param("repo", Schema.String);
44+
45+class GitHubReposApi extends HttpApiGroup.make("repos").add(
46+ HttpApiEndpoint.get("getRepo")`/repos/${githubOwnerParam}/${githubRepoParam}`.addSuccess(
47+ Schema.Unknown,
48+ ),
49+) {}
50+
51+class GitHubApi extends HttpApi.make("github").add(GitHubReposApi) {}
52+
53+const githubOpenApiSpec = OpenApi.fromApi(GitHubApi);
54+
55+const getHeaderValue = (req: IncomingMessage, key: string): string | null => {
56+ const value = req.headers[key];
57+ if (typeof value === "string") {
58+ return value;
59+ }
60+
61+ if (Array.isArray(value)) {
62+ return value[0] ?? null;
63+ }
64+
65+ return null;
66+};
67+
68+const makeTestServer = Effect.acquireRelease(
69+ Effect.promise<TestServer>(
70+ () =>
71+ new Promise<TestServer>((resolve, reject) => {
72+ const requests: Array<string> = [];
73+
74+ const server = createServer((req, res) => {
75+ const host = getHeaderValue(req, "host") ?? "127.0.0.1";
76+ const url = new URL(req.url ?? "/", `http://${host}`);
77+
78+ if (url.pathname === "/repos/octocat/hello-world" && req.method === "GET") {
79+ requests.push(url.pathname);
80+ res.statusCode = 200;
81+ res.setHeader("content-type", "application/json");
82+ res.end(
83+ JSON.stringify({
84+ full_name: "octocat/hello-world",
85+ stargazers_count: 42,
86+ }),
87+ );
88+ return;
89+ }
90+
91+ res.statusCode = 404;
92+ res.setHeader("content-type", "application/json");
93+ res.end(JSON.stringify({ error: "not found" }));
94+ });
95+
96+ server.once("error", (error) => reject(error));
97+ server.listen(0, "127.0.0.1", () => {
98+ const address = server.address();
99+ if (!address || typeof address === "string") {
100+ reject(new Error("failed to resolve test server address"));
101+ return;
102+ }
103+
104+ resolve({
105+ baseUrl: `http://127.0.0.1:${address.port}`,
106+ requests,
107+ close: () =>
108+ new Promise<void>((closeResolve, closeReject) => {
109+ server.close((error) => {
110+ if (error) {
111+ closeReject(error);
112+ return;
113+ }
114+
115+ closeResolve();
116+ });
117+ }),
118+ });
119+ });
120+ }),
121+ ),
122+ (server) => Effect.promise(() => server.close()).pipe(Effect.orDie),
123+);
124+
125+const withFixedRandomUuid = <A>(
126+ fixedValue: string,
127+ run: () => Effect.Effect<A>,
128+): Effect.Effect<A> =>
129+ Effect.acquireUseRelease(
130+ Effect.sync(() => {
131+ const original = crypto.randomUUID;
132+ (crypto as { randomUUID: () => string }).randomUUID = () => fixedValue;
133+ return original;
134+ }),
135+ () => run(),
136+ (original) =>
137+ Effect.sync(() => {
138+ (crypto as { randomUUID: () => string }).randomUUID = original;
139+ }).pipe(Effect.orDie),
140+ );
141+
142+const setupApprovalRuntimeHarness = (runId: string) =>
143+ Effect.gen(function* () {
144+ const stateDir = yield* Effect.acquireRelease(
145+ Effect.promise(() =>
146+ mkdtemp(path.join(tmpdir(), "executor-v2-approval-e2e-")),
147+ ),
148+ (directory) =>
149+ Effect.promise(() =>
150+ rm(directory, { recursive: true, force: true }),
151+ ).pipe(Effect.orDie),
152+ );
153+
154+ const persistence = yield* Effect.acquireRelease(
155+ makeSqlControlPlanePersistence({
156+ sqlitePath: path.resolve(stateDir, "control-plane.sqlite"),
157+ }),
158+ (resource) => Effect.promise(() => resource.close()).pipe(Effect.orDie),
159+ );
160+
161+ const server = yield* makeTestServer;
162+
163+ const source: Source = decodeSource({
164+ id: "src_github",
165+ workspaceId: "ws_local",
166+ name: "github",
167+ kind: "openapi",
168+ endpoint: server.baseUrl,
169+ status: "connected",
170+ enabled: true,
171+ configJson: JSON.stringify({ baseUrl: server.baseUrl }),
172+ sourceHash: null,
173+ lastError: null,
174+ createdAt: Date.now(),
175+ updatedAt: Date.now(),
176+ });
177+
178+ yield* persistence.sourceStore.upsert(source);
179+
180+ const sourceManager = makeSourceManagerService(persistence.toolArtifactStore);
181+ yield* sourceManager.refreshOpenApiArtifact({
182+ source,
183+ openApiSpec: githubOpenApiSpec,
184+ });
185+
186+ const approvalsService = createPmApprovalsService(persistence.rows);
187+ const approvalPolicy = createPmPersistentToolApprovalPolicy(persistence.rows, {
188+ requireApprovals: true,
189+ retryAfterMs: 50,
190+ });
191+
192+ const toolRegistry = createSourceToolRegistry({
193+ workspaceId: source.workspaceId,
194+ sourceStore: persistence.sourceStore,
195+ toolArtifactStore: persistence.toolArtifactStore,
196+ toolProviderRegistry: makeToolProviderRegistry([makeOpenApiToolProvider()]),
197+ approvalPolicy,
198+ });
199+
200+ const discovered = yield* toolRegistry.discover({ query: "repo", limit: 5 });
201+ const toolPath = discovered.bestPath;
202+ if (!toolPath) {
203+ throw new Error("expected source tool discovery to return a bestPath");
204+ }
205+
206+ const toolPathAccessor = toolPath
207+ .split(".")
208+ .map((segment) => `[${JSON.stringify(segment)}]`)
209+ .join("");
210+
211+ const code = `
212+const response = await tools${toolPathAccessor}({ owner: "octocat", repo: "hello-world" });
213+return response.body.full_name;
214+`;
215+
216+ const runtimeAdapters = makeRuntimeAdapterRegistry([
217+ makeLocalInProcessRuntimeAdapter(),
218+ ]);
219+
220+ const executeRuntimeRun = createPmExecuteRuntimeRun({
221+ defaultRuntimeKind: "local-inproc",
222+ runtimeAdapters,
223+ toolRegistry,
224+ });
225+
226+ const executor = createRunExecutor(executeRuntimeRun, {
227+ makeRunId: () => runId,
228+ });
229+
230+ return {
231+ persistence,
232+ server,
233+ source,
234+ approvalsService,
235+ executor,
236+ code,
237+ };
238+ });
239+
240+describe("PM approval execution E2E", () => {
241+ it.scoped("persists pending approval, resolves it, and completes sandbox tool call", () =>
242+ Effect.gen(function* () {
243+ const { persistence, server, source, approvalsService, executor, code } =
244+ yield* setupApprovalRuntimeHarness("run_approval_e2e");
245+
246+ const firstAttempt = yield* withFixedRandomUuid("approval_call_e2e", () =>
247+ executor.executeRun({ code }),
248+ );
249+
250+ expect(firstAttempt.status).toBe("failed");
251+ if (firstAttempt.status === "failed") {
252+ expect(firstAttempt.error).toContain("requires approval");
253+ }
254+
255+ const approvalsAfterFirstAttempt = yield* persistence.rows.approvals.list();
256+ expect(approvalsAfterFirstAttempt).toHaveLength(1);
257+
258+ const pendingApproval = approvalsAfterFirstAttempt[0];
259+ if (!pendingApproval) {
260+ throw new Error("expected pending approval record");
261+ }
262+
263+ expect(pendingApproval.status).toBe("pending");
264+
265+ yield* approvalsService.resolveApproval({
266+ workspaceId: source.workspaceId,
267+ approvalId: pendingApproval.id,
268+ payload: {
269+ status: "approved",
270+ reason: "approved in e2e test",
271+ },
272+ });
273+
274+ const secondAttempt = yield* withFixedRandomUuid("approval_call_e2e", () =>
275+ executor.executeRun({ code }),
276+ );
277+
278+ expect(secondAttempt.status).toBe("completed");
279+ if (secondAttempt.status === "completed") {
280+ expect(secondAttempt.result).toBe("octocat/hello-world");
281+ }
282+
283+ const approvalsAfterSecondAttempt = yield* persistence.rows.approvals.list();
284+ expect(approvalsAfterSecondAttempt[0]?.status).toBe("approved");
285+ expect(server.requests).toEqual(["/repos/octocat/hello-world"]);
286+ }),
287+ );
288+
289+ it.scoped("persists pending approval and blocks execution when denied", () =>
290+ Effect.gen(function* () {
291+ const { persistence, server, source, approvalsService, executor, code } =
292+ yield* setupApprovalRuntimeHarness("run_approval_e2e_denied");
293+
294+ const firstAttempt = yield* withFixedRandomUuid("approval_call_e2e_denied", () =>
295+ executor.executeRun({ code }),
296+ );
297+
298+ expect(firstAttempt.status).toBe("failed");
299+ if (firstAttempt.status === "failed") {
300+ expect(firstAttempt.error).toContain("requires approval");
301+ }
302+
303+ const approvalsAfterFirstAttempt = yield* persistence.rows.approvals.list();
304+ expect(approvalsAfterFirstAttempt).toHaveLength(1);
305+
306+ const pendingApproval = approvalsAfterFirstAttempt[0];
307+ if (!pendingApproval) {
308+ throw new Error("expected pending approval record");
309+ }
310+
311+ expect(pendingApproval.status).toBe("pending");
312+
313+ yield* approvalsService.resolveApproval({
314+ workspaceId: source.workspaceId,
315+ approvalId: pendingApproval.id,
316+ payload: {
317+ status: "denied",
318+ reason: "denied in e2e test",
319+ },
320+ });
321+
322+ const secondAttempt = yield* withFixedRandomUuid("approval_call_e2e_denied", () =>
323+ executor.executeRun({ code }),
324+ );
325+
326+ expect(secondAttempt.status).toBe("failed");
327+ if (secondAttempt.status === "failed") {
328+ expect((secondAttempt.error ?? "").toLowerCase()).toContain("denied");
329+ }
330+
331+ const approvalsAfterSecondAttempt = yield* persistence.rows.approvals.list();
332+ expect(approvalsAfterSecondAttempt[0]?.status).toBe("denied");
333+ expect(server.requests).toEqual([]);
334+ }),
335+ );
336+});
apps/pm/src/execute.e2e.test.ts+17−2
@@ -1,5 +1,8 @@
11 import { spawn } from "node:child_process";
2+import { mkdtemp, rm } from "node:fs/promises";
23 import { createServer } from "node:net";
4+import { tmpdir } from "node:os";
5+import * as path from "node:path";
36 import { Client } from "@modelcontextprotocol/sdk/client/index.js";
47 import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
58 import { describe, expect, it } from "@effect/vitest";
@@ -84,7 +87,15 @@ const waitForHealth = (port: number) => · 78 unmodified lines
8487 });
8588 });
8689
87−const withPmProcess = (port: number) =>
90+const withStateDir = Effect.acquireRelease(
91+ Effect.promise(() => mkdtemp(path.join(tmpdir(), "executor-v2-pm-e2e-"))),
92+ (directory) =>
93+ Effect.promise(() => rm(directory, { recursive: true, force: true })).pipe(
94+ Effect.orDie,
95+ ),
96+);
97+
98+const withPmProcess = (port: number, sqlitePath: string) =>
8899 Effect.acquireRelease(
89100 Effect.sync(() =>
90101 spawn("bun", ["src/main.ts"], {
@@ -92,6 +103,7 @@ const withPmProcess = (port: number) => · 1 unmodified line
92103 env: {
93104 ...process.env,
94105 PORT: String(port),
106+ PM_CONTROL_PLANE_SQLITE_PATH: sqlitePath,
95107 },
96108 stdio: "pipe",
97109 }),
@@ -140,7 +152,10 @@ describe("PM execute E2E", () => { · 42 unmodified lines
140152 Effect.scoped(
141153 Effect.gen(function* () {
142154 const port = yield* findFreePort;
143− yield* withPmProcess(port);
155+ const stateDir = yield* withStateDir;
156+ const sqlitePath = path.resolve(stateDir, "control-plane.sqlite");
157+
158+ yield* withPmProcess(port, sqlitePath);
144159 yield* waitForHealth(port);
145160
146161 const { client } = yield* withMcpClient(port);
bun.lock+117−0
@@ -169,6 +169,9 @@ · 168 unmodified lines
169169 "effect": "catalog:",
170170 "postgres": "^3.4.7",
171171 },
172+ "devDependencies": {
173+ "drizzle-kit": "^0.31.9",
174+ },
172175 },
173176 "packages/runtime-cloudflare-worker-loader": {
174177 "name": "@executor-v2/runtime-cloudflare-worker-loader",
@@ -320,6 +323,8 @@ · 145 unmodified lines
320323
321324 "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
322325
326+ "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
327+
323328 "@edge-runtime/format": ["@edge-runtime/format@2.2.1", "", {}, "sha512-JQTRVuiusQLNNLe2W9tnzBlV/GvSVcozLl4XZHk5swnRZ/v6jp8TqR8P7sqmJsQqblDZ3EztcWmLDbhRje/+8g=="],
324329
325330 "@edge-runtime/node-utils": ["@edge-runtime/node-utils@2.3.0", "", {}, "sha512-uUtx8BFoO1hNxtHjp3eqVPC/mWImGb2exOfGjMLUoipuWgjej+f4o/VP4bUI8U40gu7Teogd5VTeZUkGvJSPOQ=="],
@@ -374,6 +379,10 @@ · 48 unmodified lines
374379
375380 "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
376381
382+ "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="],
383+
384+ "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
385+
377386 "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A=="],
378387
379388 "@esbuild/android-arm": ["@esbuild/android-arm@0.27.0", "", { "os": "android", "cpu": "arm" }, "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ=="],
@@ -1034,6 +1043,8 @@ · 654 unmodified lines
10341043
10351044 "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
10361045
1046+ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
1047+
10371048 "bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
10381049
10391050 "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
@@ -1184,6 +1195,8 @@ · 144 unmodified lines
11841195
11851196 "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
11861197
1198+ "drizzle-kit": ["drizzle-kit@0.31.9", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-GViD3IgsXn7trFyBUUHyTFBpH/FsHTxYJ66qdbVggxef4UBPHRYxQaRzYLTuekYnk9i5FIEL9pbBIwMqX/Uwrg=="],
1199+
11871200 "drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="],
11881201
11891202 "dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="],
@@ -1224,6 +1237,8 @@ · 34 unmodified lines
12241237
12251238 "esbuild": ["esbuild@0.27.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.0", "@esbuild/android-arm": "0.27.0", "@esbuild/android-arm64": "0.27.0", "@esbuild/android-x64": "0.27.0", "@esbuild/darwin-arm64": "0.27.0", "@esbuild/darwin-x64": "0.27.0", "@esbuild/freebsd-arm64": "0.27.0", "@esbuild/freebsd-x64": "0.27.0", "@esbuild/linux-arm": "0.27.0", "@esbuild/linux-arm64": "0.27.0", "@esbuild/linux-ia32": "0.27.0", "@esbuild/linux-loong64": "0.27.0", "@esbuild/linux-mips64el": "0.27.0", "@esbuild/linux-ppc64": "0.27.0", "@esbuild/linux-riscv64": "0.27.0", "@esbuild/linux-s390x": "0.27.0", "@esbuild/linux-x64": "0.27.0", "@esbuild/netbsd-arm64": "0.27.0", "@esbuild/netbsd-x64": "0.27.0", "@esbuild/openbsd-arm64": "0.27.0", "@esbuild/openbsd-x64": "0.27.0", "@esbuild/openharmony-arm64": "0.27.0", "@esbuild/sunos-x64": "0.27.0", "@esbuild/win32-arm64": "0.27.0", "@esbuild/win32-ia32": "0.27.0", "@esbuild/win32-x64": "0.27.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA=="],
12261239
1240+ "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
1241+
12271242 "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
12281243
12291244 "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
@@ -1972,6 +1987,8 @@ · 742 unmodified lines
19721987
19731988 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
19741989
1990+ "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
1991+
19751992 "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
19761993
19771994 "srvx": ["srvx@0.8.9", "", { "dependencies": { "cookie-es": "^2.0.0" }, "bin": { "srvx": "bin/srvx.mjs" } }, "sha512-wYc3VLZHRzwYrWJhkEqkhLb31TI0SOkfYZDkUhXdp3NoCnNS0FqajiQszZZjfow/VYEuc6Q5sZh9nM6kPy2NBQ=="],
@@ -2298,6 +2315,8 @@ · 320 unmodified lines
22982315
22992316 "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
23002317
2318+ "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
2319+
23012320 "@executor-v2/app-www/tailwindcss": ["tailwindcss@3.4.19", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ=="],
23022321
23032322 "@mapbox/node-pre-gyp/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
@@ -2406,6 +2425,8 @@ · 102 unmodified lines
24062425
24072426 "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
24082427
2428+ "drizzle-kit/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
2429+
24092430 "edge-runtime/async-listen": ["async-listen@3.0.1", "", {}, "sha512-cWMaNwUJnf37C/S5TfCkk/15MwbPRwVYALA2jtjkbHjCmAPiDXyNJy2q3p1KAZzDLHAWyarUWSujUoHR4pEgrA=="],
24102431
24112432 "edge-runtime/picocolors": ["picocolors@1.0.0", "", {}, "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="],
@@ -2494,6 +2515,50 @@ · 82 unmodified lines
24942515
24952516 "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
24962517
2518+ "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
2519+
2520+ "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
2521+
2522+ "@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="],
2523+
2524+ "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="],
2525+
2526+ "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="],
2527+
2528+ "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="],
2529+
2530+ "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="],
2531+
2532+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="],
2533+
2534+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="],
2535+
2536+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="],
2537+
2538+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="],
2539+
2540+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="],
2541+
2542+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="],
2543+
2544+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="],
2545+
2546+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="],
2547+
2548+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="],
2549+
2550+ "@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="],
2551+
2552+ "@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="],
2553+
2554+ "@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="],
2555+
2556+ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="],
2557+
2558+ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="],
2559+
2560+ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
2561+
24972562 "@executor-v2/app-www/tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
24982563
24992564 "@ts-morph/common/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
@@ -2584,6 +2649,58 @@ · 84 unmodified lines
25842649
25852650 "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
25862651
2652+ "drizzle-kit/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
2653+
2654+ "drizzle-kit/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],
2655+
2656+ "drizzle-kit/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="],
2657+
2658+ "drizzle-kit/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="],
2659+
2660+ "drizzle-kit/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="],
2661+
2662+ "drizzle-kit/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="],
2663+
2664+ "drizzle-kit/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="],
2665+
2666+ "drizzle-kit/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="],
2667+
2668+ "drizzle-kit/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="],
2669+
2670+ "drizzle-kit/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="],
2671+
2672+ "drizzle-kit/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="],
2673+
2674+ "drizzle-kit/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="],
2675+
2676+ "drizzle-kit/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="],
2677+
2678+ "drizzle-kit/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="],
2679+
2680+ "drizzle-kit/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="],
2681+
2682+ "drizzle-kit/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="],
2683+
2684+ "drizzle-kit/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="],
2685+
2686+ "drizzle-kit/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="],
2687+
2688+ "drizzle-kit/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="],
2689+
2690+ "drizzle-kit/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="],
2691+
2692+ "drizzle-kit/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="],
2693+
2694+ "drizzle-kit/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="],
2695+
2696+ "drizzle-kit/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="],
2697+
2698+ "drizzle-kit/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="],
2699+
2700+ "drizzle-kit/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="],
2701+
2702+ "drizzle-kit/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
2703+
25872704 "express/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
25882705
25892706 "micro/raw-body/bytes": ["bytes@3.1.0", "", {}, "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="],
packages/persistence-sql/drizzle.config.pg.ts+14−0
@@ -0,0 +1,14 @@
1+import { defineConfig } from "drizzle-kit";
2+
3+const databaseUrl = process.env.DATABASE_URL ?? "postgres://localhost:5432/executor_v2";
4+
5+export default defineConfig({
6+ dialect: "postgresql",
7+ schema: "./src/schema-pg.ts",
8+ out: "./drizzle/postgres",
9+ dbCredentials: {
10+ url: databaseUrl,
11+ },
12+ strict: true,
13+ verbose: true,
14+});
packages/persistence-sql/drizzle.config.ts+12−0
@@ -0,0 +1,12 @@
1+import { defineConfig } from "drizzle-kit";
2+
3+export default defineConfig({
4+ dialect: "sqlite",
5+ schema: "./src/schema.ts",
6+ out: "./drizzle/sqlite",
7+ dbCredentials: {
8+ url: "./.executor-v2/control-plane.sqlite",
9+ },
10+ strict: true,
11+ verbose: true,
12+});
packages/persistence-sql/drizzle/0000_initial_schema.sql+0−139
@@ -1,139 +0,0 @@
1−CREATE TABLE IF NOT EXISTS profile (
2− id BIGINT PRIMARY KEY,
3− schema_version BIGINT NOT NULL,
4− generated_at BIGINT NOT NULL,
5− profile_json TEXT NOT NULL,
6− updated_at BIGINT NOT NULL,
7− CHECK (id = 1)
8−);
9−--> statement-breakpoint
10−
11−CREATE TABLE IF NOT EXISTS organizations (
12− id TEXT PRIMARY KEY,
13− payload_json TEXT NOT NULL,
14− updated_at BIGINT NOT NULL
15−);
16−--> statement-breakpoint
17−
18−CREATE TABLE IF NOT EXISTS organization_memberships (
19− id TEXT PRIMARY KEY,
20− workspace_id TEXT NULL,
21− payload_json TEXT NOT NULL,
22− updated_at BIGINT NOT NULL
23−);
24−--> statement-breakpoint
25−
26−CREATE TABLE IF NOT EXISTS workspaces (
27− id TEXT PRIMARY KEY,
28− workspace_id TEXT NULL,
29− payload_json TEXT NOT NULL,
30− updated_at BIGINT NOT NULL
31−);
32−--> statement-breakpoint
33−
34−CREATE TABLE IF NOT EXISTS sources (
35− workspace_id TEXT NOT NULL,
36− source_id TEXT NOT NULL,
37− name TEXT NOT NULL,
38− payload_json TEXT NOT NULL,
39− updated_at BIGINT NOT NULL,
40− PRIMARY KEY (workspace_id, source_id)
41−);
42−--> statement-breakpoint
43−
44−CREATE INDEX IF NOT EXISTS sources_workspace_name_idx
45−ON sources (workspace_id, name);
46−--> statement-breakpoint
47−
48−CREATE TABLE IF NOT EXISTS tool_artifacts (
49− workspace_id TEXT NOT NULL,
50− source_id TEXT NOT NULL,
51− payload_json TEXT NOT NULL,
52− updated_at BIGINT NOT NULL,
53− PRIMARY KEY (workspace_id, source_id)
54−);
55−--> statement-breakpoint
56−
57−CREATE TABLE IF NOT EXISTS auth_connections (
58− id TEXT PRIMARY KEY,
59− workspace_id TEXT NULL,
60− payload_json TEXT NOT NULL,
61− updated_at BIGINT NOT NULL
62−);
63−--> statement-breakpoint
64−
65−CREATE TABLE IF NOT EXISTS source_auth_bindings (
66− id TEXT PRIMARY KEY,
67− workspace_id TEXT NULL,
68− payload_json TEXT NOT NULL,
69− updated_at BIGINT NOT NULL
70−);
71−--> statement-breakpoint
72−
73−CREATE TABLE IF NOT EXISTS auth_materials (
74− id TEXT PRIMARY KEY,
75− workspace_id TEXT NULL,
76− payload_json TEXT NOT NULL,
77− updated_at BIGINT NOT NULL
78−);
79−--> statement-breakpoint
80−
81−CREATE TABLE IF NOT EXISTS oauth_states (
82− id TEXT PRIMARY KEY,
83− workspace_id TEXT NULL,
84− payload_json TEXT NOT NULL,
85− updated_at BIGINT NOT NULL
86−);
87−--> statement-breakpoint
88−
89−CREATE TABLE IF NOT EXISTS policies (
90− id TEXT PRIMARY KEY,
91− workspace_id TEXT NULL,
92− payload_json TEXT NOT NULL,
93− updated_at BIGINT NOT NULL
94−);
95−--> statement-breakpoint
96−
97−CREATE TABLE IF NOT EXISTS approvals (
98− id TEXT PRIMARY KEY,
99− workspace_id TEXT NULL,
100− payload_json TEXT NOT NULL,
101− updated_at BIGINT NOT NULL
102−);
103−--> statement-breakpoint
104−
105−CREATE TABLE IF NOT EXISTS task_runs (
106− id TEXT PRIMARY KEY,
107− workspace_id TEXT NULL,
108− payload_json TEXT NOT NULL,
109− updated_at BIGINT NOT NULL
110−);
111−--> statement-breakpoint
112−
113−CREATE TABLE IF NOT EXISTS storage_instances (
114− id TEXT PRIMARY KEY,
115− workspace_id TEXT NULL,
116− payload_json TEXT NOT NULL,
117− updated_at BIGINT NOT NULL
118−);
119−--> statement-breakpoint
120−
121−CREATE TABLE IF NOT EXISTS sync_states (
122− id TEXT PRIMARY KEY,
123− workspace_id TEXT NULL,
124− payload_json TEXT NOT NULL,
125− updated_at BIGINT NOT NULL
126−);
127−--> statement-breakpoint
128−
129−CREATE TABLE IF NOT EXISTS events (
130− id TEXT PRIMARY KEY,
131− workspace_id TEXT NOT NULL,
132− sequence BIGINT NOT NULL,
133− event_json TEXT NOT NULL,
134− created_at BIGINT NOT NULL
135−);
136−--> statement-breakpoint
137−
138−CREATE UNIQUE INDEX IF NOT EXISTS events_workspace_sequence_idx
139−ON events (workspace_id, sequence);
packages/persistence-sql/drizzle/meta/_journal.json+0−13
@@ -1,13 +0,0 @@
1−{
2− "version": "1",
3− "dialect": "sqlite",
4− "entries": [
5− {
6− "idx": 0,
7− "version": "1",
8− "when": 1700000000000,
9− "tag": "0000_initial_schema",
10− "breakpoints": true
11− }
12− ]
13−}
packages/persistence-sql/drizzle/postgres/0000_spicy_barracuda.sql+224−0
@@ -0,0 +1,224 @@
1+CREATE TABLE "approvals" (
2+ "id" text PRIMARY KEY NOT NULL,
3+ "workspace_id" text NOT NULL,
4+ "task_run_id" text NOT NULL,
5+ "call_id" text NOT NULL,
6+ "tool_path" text NOT NULL,
7+ "status" text NOT NULL,
8+ "input_preview_json" text NOT NULL,
9+ "reason" text,
10+ "requested_at" bigint NOT NULL,
11+ "resolved_at" bigint
12+);
13+--> statement-breakpoint
14+CREATE TABLE "auth_connections" (
15+ "id" text PRIMARY KEY NOT NULL,
16+ "organization_id" text NOT NULL,
17+ "workspace_id" text,
18+ "account_id" text,
19+ "owner_type" text NOT NULL,
20+ "strategy" text NOT NULL,
21+ "display_name" text NOT NULL,
22+ "status" text NOT NULL,
23+ "status_reason" text,
24+ "last_auth_error_class" text,
25+ "metadata_json" text,
26+ "additional_headers_json" text,
27+ "created_by_account_id" text,
28+ "created_at" bigint NOT NULL,
29+ "updated_at" bigint NOT NULL,
30+ "last_used_at" bigint
31+);
32+--> statement-breakpoint
33+CREATE TABLE "auth_materials" (
34+ "id" text PRIMARY KEY NOT NULL,
35+ "connection_id" text NOT NULL,
36+ "ciphertext" text NOT NULL,
37+ "key_version" text NOT NULL,
38+ "created_at" bigint NOT NULL,
39+ "updated_at" bigint NOT NULL
40+);
41+--> statement-breakpoint
42+CREATE TABLE "oauth_states" (
43+ "id" text PRIMARY KEY NOT NULL,
44+ "connection_id" text NOT NULL,
45+ "access_token_ciphertext" text NOT NULL,
46+ "refresh_token_ciphertext" text,
47+ "key_version" text NOT NULL,
48+ "expires_at" bigint,
49+ "scope" text,
50+ "token_type" text,
51+ "issuer" text,
52+ "refresh_config_json" text,
53+ "token_version" bigint NOT NULL,
54+ "lease_holder" text,
55+ "lease_expires_at" bigint,
56+ "lease_fence" bigint NOT NULL,
57+ "last_refresh_at" bigint,
58+ "last_refresh_error_class" text,
59+ "last_refresh_error" text,
60+ "reauth_required_at" bigint,
61+ "created_at" bigint NOT NULL,
62+ "updated_at" bigint NOT NULL
63+);
64+--> statement-breakpoint
65+CREATE TABLE "organization_memberships" (
66+ "id" text PRIMARY KEY NOT NULL,
67+ "organization_id" text NOT NULL,
68+ "account_id" text NOT NULL,
69+ "role" text NOT NULL,
70+ "status" text NOT NULL,
71+ "billable" boolean NOT NULL,
72+ "invited_by_account_id" text,
73+ "joined_at" bigint,
74+ "created_at" bigint NOT NULL,
75+ "updated_at" bigint NOT NULL
76+);
77+--> statement-breakpoint
78+CREATE TABLE "organizations" (
79+ "id" text PRIMARY KEY NOT NULL,
80+ "slug" text NOT NULL,
81+ "name" text NOT NULL,
82+ "status" text NOT NULL,
83+ "created_by_account_id" text,
84+ "created_at" bigint NOT NULL,
85+ "updated_at" bigint NOT NULL
86+);
87+--> statement-breakpoint
88+CREATE TABLE "policies" (
89+ "id" text PRIMARY KEY NOT NULL,
90+ "workspace_id" text NOT NULL,
91+ "tool_path_pattern" text NOT NULL,
92+ "decision" text NOT NULL,
93+ "created_at" bigint NOT NULL,
94+ "updated_at" bigint NOT NULL
95+);
96+--> statement-breakpoint
97+CREATE TABLE "profile" (
98+ "id" text PRIMARY KEY NOT NULL,
99+ "default_workspace_id" text,
100+ "display_name" text NOT NULL,
101+ "runtime_mode" text NOT NULL,
102+ "created_at" bigint NOT NULL,
103+ "updated_at" bigint NOT NULL
104+);
105+--> statement-breakpoint
106+CREATE TABLE "source_auth_bindings" (
107+ "id" text PRIMARY KEY NOT NULL,
108+ "source_id" text NOT NULL,
109+ "connection_id" text NOT NULL,
110+ "organization_id" text NOT NULL,
111+ "workspace_id" text,
112+ "account_id" text,
113+ "scope_type" text NOT NULL,
114+ "selector" text,
115+ "enabled" boolean NOT NULL,
116+ "created_at" bigint NOT NULL,
117+ "updated_at" bigint NOT NULL
118+);
119+--> statement-breakpoint
120+CREATE TABLE "sources" (
121+ "workspace_id" text NOT NULL,
122+ "source_id" text NOT NULL,
123+ "name" text NOT NULL,
124+ "kind" text NOT NULL,
125+ "endpoint" text NOT NULL,
126+ "status" text NOT NULL,
127+ "enabled" boolean NOT NULL,
128+ "config_json" text NOT NULL,
129+ "source_hash" text,
130+ "last_error" text,
131+ "created_at" bigint NOT NULL,
132+ "updated_at" bigint NOT NULL,
133+ CONSTRAINT "sources_workspace_id_source_id_pk" PRIMARY KEY("workspace_id","source_id")
134+);
135+--> statement-breakpoint
136+CREATE TABLE "storage_instances" (
137+ "id" text PRIMARY KEY NOT NULL,
138+ "scope_type" text NOT NULL,
139+ "durability" text NOT NULL,
140+ "status" text NOT NULL,
141+ "provider" text NOT NULL,
142+ "backend_key" text NOT NULL,
143+ "organization_id" text NOT NULL,
144+ "workspace_id" text,
145+ "account_id" text,
146+ "created_by_account_id" text,
147+ "purpose" text,
148+ "size_bytes" bigint,
149+ "file_count" bigint,
150+ "created_at" bigint NOT NULL,
151+ "updated_at" bigint NOT NULL,
152+ "last_seen_at" bigint NOT NULL,
153+ "closed_at" bigint,
154+ "expires_at" bigint
155+);
156+--> statement-breakpoint
157+CREATE TABLE "sync_states" (
158+ "id" text PRIMARY KEY NOT NULL,
159+ "workspace_id" text NOT NULL,
160+ "target" text NOT NULL,
161+ "target_url" text NOT NULL,
162+ "linked_subject" text,
163+ "cursor" text,
164+ "last_sync_at" bigint,
165+ "updated_at" bigint NOT NULL
166+);
167+--> statement-breakpoint
168+CREATE TABLE "task_runs" (
169+ "id" text PRIMARY KEY NOT NULL,
170+ "workspace_id" text NOT NULL,
171+ "account_id" text NOT NULL,
172+ "session_id" text NOT NULL,
173+ "runtime_id" text NOT NULL,
174+ "code_hash" text NOT NULL,
175+ "status" text NOT NULL,
176+ "started_at" bigint,
177+ "completed_at" bigint,
178+ "exit_code" bigint,
179+ "error" text
180+);
181+--> statement-breakpoint
182+CREATE TABLE "tool_artifacts" (
183+ "id" text NOT NULL,
184+ "workspace_id" text NOT NULL,
185+ "source_id" text NOT NULL,
186+ "source_hash" text NOT NULL,
187+ "tool_count" bigint NOT NULL,
188+ "manifest_json" text NOT NULL,
189+ "created_at" bigint NOT NULL,
190+ "updated_at" bigint NOT NULL,
191+ CONSTRAINT "tool_artifacts_workspace_id_source_id_pk" PRIMARY KEY("workspace_id","source_id")
192+);
193+--> statement-breakpoint
194+CREATE TABLE "workspaces" (
195+ "id" text PRIMARY KEY NOT NULL,
196+ "organization_id" text NOT NULL,
197+ "name" text NOT NULL,
198+ "created_by_account_id" text,
199+ "created_at" bigint NOT NULL,
200+ "updated_at" bigint NOT NULL
201+);
202+--> statement-breakpoint
203+CREATE INDEX "approvals_workspace_idx" ON "approvals" USING btree ("workspace_id");--> statement-breakpoint
204+CREATE INDEX "approvals_task_run_idx" ON "approvals" USING btree ("task_run_id");--> statement-breakpoint
205+CREATE INDEX "auth_connections_org_idx" ON "auth_connections" USING btree ("organization_id");--> statement-breakpoint
206+CREATE INDEX "auth_connections_workspace_idx" ON "auth_connections" USING btree ("workspace_id");--> statement-breakpoint
207+CREATE INDEX "auth_connections_account_idx" ON "auth_connections" USING btree ("account_id");--> statement-breakpoint
208+CREATE INDEX "auth_materials_connection_idx" ON "auth_materials" USING btree ("connection_id");--> statement-breakpoint
209+CREATE INDEX "oauth_states_connection_idx" ON "oauth_states" USING btree ("connection_id");--> statement-breakpoint
210+CREATE INDEX "organization_memberships_org_idx" ON "organization_memberships" USING btree ("organization_id");--> statement-breakpoint
211+CREATE INDEX "organization_memberships_account_idx" ON "organization_memberships" USING btree ("account_id");--> statement-breakpoint
212+CREATE INDEX "policies_workspace_idx" ON "policies" USING btree ("workspace_id");--> statement-breakpoint
213+CREATE INDEX "source_auth_bindings_source_idx" ON "source_auth_bindings" USING btree ("source_id");--> statement-breakpoint
214+CREATE INDEX "source_auth_bindings_connection_idx" ON "source_auth_bindings" USING btree ("connection_id");--> statement-breakpoint
215+CREATE INDEX "source_auth_bindings_org_idx" ON "source_auth_bindings" USING btree ("organization_id");--> statement-breakpoint
216+CREATE INDEX "source_auth_bindings_workspace_idx" ON "source_auth_bindings" USING btree ("workspace_id");--> statement-breakpoint
217+CREATE INDEX "source_auth_bindings_account_idx" ON "source_auth_bindings" USING btree ("account_id");--> statement-breakpoint
218+CREATE INDEX "sources_workspace_name_idx" ON "sources" USING btree ("workspace_id","name");--> statement-breakpoint
219+CREATE INDEX "storage_instances_org_idx" ON "storage_instances" USING btree ("organization_id");--> statement-breakpoint
220+CREATE INDEX "storage_instances_workspace_idx" ON "storage_instances" USING btree ("workspace_id");--> statement-breakpoint
221+CREATE INDEX "sync_states_workspace_idx" ON "sync_states" USING btree ("workspace_id");--> statement-breakpoint
222+CREATE INDEX "task_runs_workspace_idx" ON "task_runs" USING btree ("workspace_id");--> statement-breakpoint
223+CREATE UNIQUE INDEX "tool_artifacts_id_idx" ON "tool_artifacts" USING btree ("id");--> statement-breakpoint
224+CREATE INDEX "workspaces_org_idx" ON "workspaces" USING btree ("organization_id");
packages/persistence-sql/drizzle/postgres/meta/0000_snapshot.json+1509−0
@@ -0,0 +1,1509 @@
1+{
2+ "id": "5ce8d2a0-b31c-4d34-bd01-c638ca0d5d87",
3+ "prevId": "00000000-0000-0000-0000-000000000000",
4+ "version": "7",
5+ "dialect": "postgresql",
6+ "tables": {
7+ "public.approvals": {
8+ "name": "approvals",
9+ "schema": "",
10+ "columns": {
11+ "id": {
12+ "name": "id",
13+ "type": "text",
14+ "primaryKey": true,
15+ "notNull": true
16+ },
17+ "workspace_id": {
18+ "name": "workspace_id",
19+ "type": "text",
20+ "primaryKey": false,
21+ "notNull": true
22+ },
23+ "task_run_id": {
24+ "name": "task_run_id",
25+ "type": "text",
26+ "primaryKey": false,
27+ "notNull": true
28+ },
29+ "call_id": {
30+ "name": "call_id",
31+ "type": "text",
32+ "primaryKey": false,
33+ "notNull": true
34+ },
35+ "tool_path": {
36+ "name": "tool_path",
37+ "type": "text",
38+ "primaryKey": false,
39+ "notNull": true
40+ },
41+ "status": {
42+ "name": "status",
43+ "type": "text",
44+ "primaryKey": false,
45+ "notNull": true
46+ },
47+ "input_preview_json": {
48+ "name": "input_preview_json",
49+ "type": "text",
50+ "primaryKey": false,
51+ "notNull": true
52+ },
53+ "reason": {
54+ "name": "reason",
55+ "type": "text",
56+ "primaryKey": false,
57+ "notNull": false
58+ },
59+ "requested_at": {
60+ "name": "requested_at",
61+ "type": "bigint",
62+ "primaryKey": false,
63+ "notNull": true
64+ },
65+ "resolved_at": {
66+ "name": "resolved_at",
67+ "type": "bigint",
68+ "primaryKey": false,
69+ "notNull": false
70+ }
71+ },
72+ "indexes": {
73+ "approvals_workspace_idx": {
74+ "name": "approvals_workspace_idx",
75+ "columns": [
76+ {
77+ "expression": "workspace_id",
78+ "isExpression": false,
79+ "asc": true,
80+ "nulls": "last"
81+ }
82+ ],
83+ "isUnique": false,
84+ "concurrently": false,
85+ "method": "btree",
86+ "with": {}
87+ },
88+ "approvals_task_run_idx": {
89+ "name": "approvals_task_run_idx",
90+ "columns": [
91+ {
92+ "expression": "task_run_id",
93+ "isExpression": false,
94+ "asc": true,
95+ "nulls": "last"
96+ }
97+ ],
98+ "isUnique": false,
99+ "concurrently": false,
100+ "method": "btree",
101+ "with": {}
102+ }
103+ },
104+ "foreignKeys": {},
105+ "compositePrimaryKeys": {},
106+ "uniqueConstraints": {},
107+ "policies": {},
108+ "checkConstraints": {},
109+ "isRLSEnabled": false
110+ },
111+ "public.auth_connections": {
112+ "name": "auth_connections",
113+ "schema": "",
114+ "columns": {
115+ "id": {
116+ "name": "id",
117+ "type": "text",
118+ "primaryKey": true,
119+ "notNull": true
120+ },
121+ "organization_id": {
122+ "name": "organization_id",
123+ "type": "text",
124+ "primaryKey": false,
125+ "notNull": true
126+ },
127+ "workspace_id": {
128+ "name": "workspace_id",
129+ "type": "text",
130+ "primaryKey": false,
131+ "notNull": false
132+ },
133+ "account_id": {
134+ "name": "account_id",
135+ "type": "text",
136+ "primaryKey": false,
137+ "notNull": false
138+ },
139+ "owner_type": {
140+ "name": "owner_type",
141+ "type": "text",
142+ "primaryKey": false,
143+ "notNull": true
144+ },
145+ "strategy": {
146+ "name": "strategy",
147+ "type": "text",
148+ "primaryKey": false,
149+ "notNull": true
150+ },
151+ "display_name": {
152+ "name": "display_name",
153+ "type": "text",
154+ "primaryKey": false,
155+ "notNull": true
156+ },
157+ "status": {
158+ "name": "status",
159+ "type": "text",
160+ "primaryKey": false,
161+ "notNull": true
162+ },
163+ "status_reason": {
164+ "name": "status_reason",
165+ "type": "text",
166+ "primaryKey": false,
167+ "notNull": false
168+ },
169+ "last_auth_error_class": {
170+ "name": "last_auth_error_class",
171+ "type": "text",
172+ "primaryKey": false,
173+ "notNull": false
174+ },
175+ "metadata_json": {
176+ "name": "metadata_json",
177+ "type": "text",
178+ "primaryKey": false,
179+ "notNull": false
180+ },
181+ "additional_headers_json": {
182+ "name": "additional_headers_json",
183+ "type": "text",
184+ "primaryKey": false,
185+ "notNull": false
186+ },
187+ "created_by_account_id": {
188+ "name": "created_by_account_id",
189+ "type": "text",
190+ "primaryKey": false,
191+ "notNull": false
192+ },
193+ "created_at": {
194+ "name": "created_at",
195+ "type": "bigint",
196+ "primaryKey": false,
197+ "notNull": true
198+ },
199+ "updated_at": {
200+ "name": "updated_at",
201+ "type": "bigint",
202+ "primaryKey": false,
203+ "notNull": true
204+ },
205+ "last_used_at": {
206+ "name": "last_used_at",
207+ "type": "bigint",
208+ "primaryKey": false,
209+ "notNull": false
210+ }
211+ },
212+ "indexes": {
213+ "auth_connections_org_idx": {
214+ "name": "auth_connections_org_idx",
215+ "columns": [
216+ {
217+ "expression": "organization_id",
218+ "isExpression": false,
219+ "asc": true,
220+ "nulls": "last"
221+ }
222+ ],
223+ "isUnique": false,
224+ "concurrently": false,
225+ "method": "btree",
226+ "with": {}
227+ },
228+ "auth_connections_workspace_idx": {
229+ "name": "auth_connections_workspace_idx",
230+ "columns": [
231+ {
232+ "expression": "workspace_id",
233+ "isExpression": false,
234+ "asc": true,
235+ "nulls": "last"
236+ }
237+ ],
238+ "isUnique": false,
239+ "concurrently": false,
240+ "method": "btree",
241+ "with": {}
242+ },
243+ "auth_connections_account_idx": {
244+ "name": "auth_connections_account_idx",
245+ "columns": [
246+ {
247+ "expression": "account_id",
248+ "isExpression": false,
249+ "asc": true,
250+ "nulls": "last"
251+ }
252+ ],
253+ "isUnique": false,
254+ "concurrently": false,
255+ "method": "btree",
256+ "with": {}
257+ }
258+ },
259+ "foreignKeys": {},
260+ "compositePrimaryKeys": {},
261+ "uniqueConstraints": {},
262+ "policies": {},
263+ "checkConstraints": {},
264+ "isRLSEnabled": false
265+ },
266+ "public.auth_materials": {
267+ "name": "auth_materials",
268+ "schema": "",
269+ "columns": {
270+ "id": {
271+ "name": "id",
272+ "type": "text",
273+ "primaryKey": true,
274+ "notNull": true
275+ },
276+ "connection_id": {
277+ "name": "connection_id",
278+ "type": "text",
279+ "primaryKey": false,
280+ "notNull": true
281+ },
282+ "ciphertext": {
283+ "name": "ciphertext",
284+ "type": "text",
285+ "primaryKey": false,
286+ "notNull": true
287+ },
288+ "key_version": {
289+ "name": "key_version",
290+ "type": "text",
291+ "primaryKey": false,
292+ "notNull": true
293+ },
294+ "created_at": {
295+ "name": "created_at",
296+ "type": "bigint",
297+ "primaryKey": false,
298+ "notNull": true
299+ },
300+ "updated_at": {
301+ "name": "updated_at",
302+ "type": "bigint",
303+ "primaryKey": false,
304+ "notNull": true
305+ }
306+ },
307+ "indexes": {
308+ "auth_materials_connection_idx": {
309+ "name": "auth_materials_connection_idx",
310+ "columns": [
311+ {
312+ "expression": "connection_id",
313+ "isExpression": false,
314+ "asc": true,
315+ "nulls": "last"
316+ }
317+ ],
318+ "isUnique": false,
319+ "concurrently": false,
320+ "method": "btree",
321+ "with": {}
322+ }
323+ },
324+ "foreignKeys": {},
325+ "compositePrimaryKeys": {},
326+ "uniqueConstraints": {},
327+ "policies": {},
328+ "checkConstraints": {},
329+ "isRLSEnabled": false
330+ },
331+ "public.oauth_states": {
332+ "name": "oauth_states",
333+ "schema": "",
334+ "columns": {
335+ "id": {
336+ "name": "id",
337+ "type": "text",
338+ "primaryKey": true,
339+ "notNull": true
340+ },
341+ "connection_id": {
342+ "name": "connection_id",
343+ "type": "text",
344+ "primaryKey": false,
345+ "notNull": true
346+ },
347+ "access_token_ciphertext": {
348+ "name": "access_token_ciphertext",
349+ "type": "text",
350+ "primaryKey": false,
351+ "notNull": true
352+ },
353+ "refresh_token_ciphertext": {
354+ "name": "refresh_token_ciphertext",
355+ "type": "text",
356+ "primaryKey": false,
357+ "notNull": false
358+ },
359+ "key_version": {
360+ "name": "key_version",
361+ "type": "text",
362+ "primaryKey": false,
363+ "notNull": true
364+ },
365+ "expires_at": {
366+ "name": "expires_at",
367+ "type": "bigint",
368+ "primaryKey": false,
369+ "notNull": false
370+ },
371+ "scope": {
372+ "name": "scope",
373+ "type": "text",
374+ "primaryKey": false,
375+ "notNull": false
376+ },
377+ "token_type": {
378+ "name": "token_type",
379+ "type": "text",
380+ "primaryKey": false,
381+ "notNull": false
382+ },
383+ "issuer": {
384+ "name": "issuer",
385+ "type": "text",
386+ "primaryKey": false,
387+ "notNull": false
388+ },
389+ "refresh_config_json": {
390+ "name": "refresh_config_json",
391+ "type": "text",
392+ "primaryKey": false,
393+ "notNull": false
394+ },
395+ "token_version": {
396+ "name": "token_version",
397+ "type": "bigint",
398+ "primaryKey": false,
399+ "notNull": true
400+ },
401+ "lease_holder": {
402+ "name": "lease_holder",
403+ "type": "text",
404+ "primaryKey": false,
405+ "notNull": false
406+ },
407+ "lease_expires_at": {
408+ "name": "lease_expires_at",
409+ "type": "bigint",
410+ "primaryKey": false,
411+ "notNull": false
412+ },
413+ "lease_fence": {
414+ "name": "lease_fence",
415+ "type": "bigint",
416+ "primaryKey": false,
417+ "notNull": true
418+ },
419+ "last_refresh_at": {
420+ "name": "last_refresh_at",
421+ "type": "bigint",
422+ "primaryKey": false,
423+ "notNull": false
424+ },
425+ "last_refresh_error_class": {
426+ "name": "last_refresh_error_class",
427+ "type": "text",
428+ "primaryKey": false,
429+ "notNull": false
430+ },
431+ "last_refresh_error": {
432+ "name": "last_refresh_error",
433+ "type": "text",
434+ "primaryKey": false,
435+ "notNull": false
436+ },
437+ "reauth_required_at": {
438+ "name": "reauth_required_at",
439+ "type": "bigint",
440+ "primaryKey": false,
441+ "notNull": false
442+ },
443+ "created_at": {
444+ "name": "created_at",
445+ "type": "bigint",
446+ "primaryKey": false,
447+ "notNull": true
448+ },
449+ "updated_at": {
450+ "name": "updated_at",
451+ "type": "bigint",
452+ "primaryKey": false,
453+ "notNull": true
454+ }
455+ },
456+ "indexes": {
457+ "oauth_states_connection_idx": {
458+ "name": "oauth_states_connection_idx",
459+ "columns": [
460+ {
461+ "expression": "connection_id",
462+ "isExpression": false,
463+ "asc": true,
464+ "nulls": "last"
465+ }
466+ ],
467+ "isUnique": false,
468+ "concurrently": false,
469+ "method": "btree",
470+ "with": {}
471+ }
472+ },
473+ "foreignKeys": {},
474+ "compositePrimaryKeys": {},
475+ "uniqueConstraints": {},
476+ "policies": {},
477+ "checkConstraints": {},
478+ "isRLSEnabled": false
479+ },
480+ "public.organization_memberships": {
481+ "name": "organization_memberships",
482+ "schema": "",
483+ "columns": {
484+ "id": {
485+ "name": "id",
486+ "type": "text",
487+ "primaryKey": true,
488+ "notNull": true
489+ },
490+ "organization_id": {
491+ "name": "organization_id",
492+ "type": "text",
493+ "primaryKey": false,
494+ "notNull": true
495+ },
496+ "account_id": {
497+ "name": "account_id",
498+ "type": "text",
499+ "primaryKey": false,
500+ "notNull": true
501+ },
502+ "role": {
503+ "name": "role",
504+ "type": "text",
505+ "primaryKey": false,
506+ "notNull": true
507+ },
508+ "status": {
509+ "name": "status",
510+ "type": "text",
511+ "primaryKey": false,
512+ "notNull": true
513+ },
514+ "billable": {
515+ "name": "billable",
516+ "type": "boolean",
517+ "primaryKey": false,
518+ "notNull": true
519+ },
520+ "invited_by_account_id": {
521+ "name": "invited_by_account_id",
522+ "type": "text",
523+ "primaryKey": false,
524+ "notNull": false
525+ },
526+ "joined_at": {
527+ "name": "joined_at",
528+ "type": "bigint",
529+ "primaryKey": false,
530+ "notNull": false
531+ },
532+ "created_at": {
533+ "name": "created_at",
534+ "type": "bigint",
535+ "primaryKey": false,
536+ "notNull": true
537+ },
538+ "updated_at": {
539+ "name": "updated_at",
540+ "type": "bigint",
541+ "primaryKey": false,
542+ "notNull": true
543+ }
544+ },
545+ "indexes": {
546+ "organization_memberships_org_idx": {
547+ "name": "organization_memberships_org_idx",
548+ "columns": [
549+ {
550+ "expression": "organization_id",
551+ "isExpression": false,
552+ "asc": true,
553+ "nulls": "last"
554+ }
555+ ],
556+ "isUnique": false,
557+ "concurrently": false,
558+ "method": "btree",
559+ "with": {}
560+ },
561+ "organization_memberships_account_idx": {
562+ "name": "organization_memberships_account_idx",
563+ "columns": [
564+ {
565+ "expression": "account_id",
566+ "isExpression": false,
567+ "asc": true,
568+ "nulls": "last"
569+ }
570+ ],
571+ "isUnique": false,
572+ "concurrently": false,
573+ "method": "btree",
574+ "with": {}
575+ }
576+ },
577+ "foreignKeys": {},
578+ "compositePrimaryKeys": {},
579+ "uniqueConstraints": {},
580+ "policies": {},
581+ "checkConstraints": {},
582+ "isRLSEnabled": false
583+ },
584+ "public.organizations": {
585+ "name": "organizations",
586+ "schema": "",
587+ "columns": {
588+ "id": {
589+ "name": "id",
590+ "type": "text",
591+ "primaryKey": true,
592+ "notNull": true
593+ },
594+ "slug": {
595+ "name": "slug",
596+ "type": "text",
597+ "primaryKey": false,
598+ "notNull": true
599+ },
600+ "name": {
601+ "name": "name",
602+ "type": "text",
603+ "primaryKey": false,
604+ "notNull": true
605+ },
606+ "status": {
607+ "name": "status",
608+ "type": "text",
609+ "primaryKey": false,
610+ "notNull": true
611+ },
612+ "created_by_account_id": {
613+ "name": "created_by_account_id",
614+ "type": "text",
615+ "primaryKey": false,
616+ "notNull": false
617+ },
618+ "created_at": {
619+ "name": "created_at",
620+ "type": "bigint",
621+ "primaryKey": false,
622+ "notNull": true
623+ },
624+ "updated_at": {
625+ "name": "updated_at",
626+ "type": "bigint",
627+ "primaryKey": false,
628+ "notNull": true
629+ }
630+ },
631+ "indexes": {},
632+ "foreignKeys": {},
633+ "compositePrimaryKeys": {},
634+ "uniqueConstraints": {},
635+ "policies": {},
636+ "checkConstraints": {},
637+ "isRLSEnabled": false
638+ },
639+ "public.policies": {
640+ "name": "policies",
641+ "schema": "",
642+ "columns": {
643+ "id": {
644+ "name": "id",
645+ "type": "text",
646+ "primaryKey": true,
647+ "notNull": true
648+ },
649+ "workspace_id": {
650+ "name": "workspace_id",
651+ "type": "text",
652+ "primaryKey": false,
653+ "notNull": true
654+ },
655+ "tool_path_pattern": {
656+ "name": "tool_path_pattern",
657+ "type": "text",
658+ "primaryKey": false,
659+ "notNull": true
660+ },
661+ "decision": {
662+ "name": "decision",
663+ "type": "text",
664+ "primaryKey": false,
665+ "notNull": true
666+ },
667+ "created_at": {
668+ "name": "created_at",
669+ "type": "bigint",
670+ "primaryKey": false,
671+ "notNull": true
672+ },
673+ "updated_at": {
674+ "name": "updated_at",
675+ "type": "bigint",
676+ "primaryKey": false,
677+ "notNull": true
678+ }
679+ },
680+ "indexes": {
681+ "policies_workspace_idx": {
682+ "name": "policies_workspace_idx",
683+ "columns": [
684+ {
685+ "expression": "workspace_id",
686+ "isExpression": false,
687+ "asc": true,
688+ "nulls": "last"
689+ }
690+ ],
691+ "isUnique": false,
692+ "concurrently": false,
693+ "method": "btree",
694+ "with": {}
695+ }
696+ },
697+ "foreignKeys": {},
698+ "compositePrimaryKeys": {},
699+ "uniqueConstraints": {},
700+ "policies": {},
701+ "checkConstraints": {},
702+ "isRLSEnabled": false
703+ },
704+ "public.profile": {
705+ "name": "profile",
706+ "schema": "",
707+ "columns": {
708+ "id": {
709+ "name": "id",
710+ "type": "text",
711+ "primaryKey": true,
712+ "notNull": true
713+ },
714+ "default_workspace_id": {
715+ "name": "default_workspace_id",
716+ "type": "text",
717+ "primaryKey": false,
718+ "notNull": false
719+ },
720+ "display_name": {
721+ "name": "display_name",
722+ "type": "text",
723+ "primaryKey": false,
724+ "notNull": true
725+ },
726+ "runtime_mode": {
727+ "name": "runtime_mode",
728+ "type": "text",
729+ "primaryKey": false,
730+ "notNull": true
731+ },
732+ "created_at": {
733+ "name": "created_at",
734+ "type": "bigint",
735+ "primaryKey": false,
736+ "notNull": true
737+ },
738+ "updated_at": {
739+ "name": "updated_at",
740+ "type": "bigint",
741+ "primaryKey": false,
742+ "notNull": true
743+ }
744+ },
745+ "indexes": {},
746+ "foreignKeys": {},
747+ "compositePrimaryKeys": {},
748+ "uniqueConstraints": {},
749+ "policies": {},
750+ "checkConstraints": {},
751+ "isRLSEnabled": false
752+ },
753+ "public.source_auth_bindings": {
754+ "name": "source_auth_bindings",
755+ "schema": "",
756+ "columns": {
757+ "id": {
758+ "name": "id",
759+ "type": "text",
760+ "primaryKey": true,
761+ "notNull": true
762+ },
763+ "source_id": {
764+ "name": "source_id",
765+ "type": "text",
766+ "primaryKey": false,
767+ "notNull": true
768+ },
769+ "connection_id": {
770+ "name": "connection_id",
771+ "type": "text",
772+ "primaryKey": false,
773+ "notNull": true
774+ },
775+ "organization_id": {
776+ "name": "organization_id",
777+ "type": "text",
778+ "primaryKey": false,
779+ "notNull": true
780+ },
781+ "workspace_id": {
782+ "name": "workspace_id",
783+ "type": "text",
784+ "primaryKey": false,
785+ "notNull": false
786+ },
787+ "account_id": {
788+ "name": "account_id",
789+ "type": "text",
790+ "primaryKey": false,
791+ "notNull": false
792+ },
793+ "scope_type": {
794+ "name": "scope_type",
795+ "type": "text",
796+ "primaryKey": false,
797+ "notNull": true
798+ },
799+ "selector": {
800+ "name": "selector",
801+ "type": "text",
802+ "primaryKey": false,
803+ "notNull": false
804+ },
805+ "enabled": {
806+ "name": "enabled",
807+ "type": "boolean",
808+ "primaryKey": false,
809+ "notNull": true
810+ },
811+ "created_at": {
812+ "name": "created_at",
813+ "type": "bigint",
814+ "primaryKey": false,
815+ "notNull": true
816+ },
817+ "updated_at": {
818+ "name": "updated_at",
819+ "type": "bigint",
820+ "primaryKey": false,
821+ "notNull": true
822+ }
823+ },
824+ "indexes": {
825+ "source_auth_bindings_source_idx": {
826+ "name": "source_auth_bindings_source_idx",
827+ "columns": [
828+ {
829+ "expression": "source_id",
830+ "isExpression": false,
831+ "asc": true,
832+ "nulls": "last"
833+ }
834+ ],
835+ "isUnique": false,
836+ "concurrently": false,
837+ "method": "btree",
838+ "with": {}
839+ },
840+ "source_auth_bindings_connection_idx": {
841+ "name": "source_auth_bindings_connection_idx",
842+ "columns": [
843+ {
844+ "expression": "connection_id",
845+ "isExpression": false,
846+ "asc": true,
847+ "nulls": "last"
848+ }
849+ ],
850+ "isUnique": false,
851+ "concurrently": false,
852+ "method": "btree",
853+ "with": {}
854+ },
855+ "source_auth_bindings_org_idx": {
856+ "name": "source_auth_bindings_org_idx",
857+ "columns": [
858+ {
859+ "expression": "organization_id",
860+ "isExpression": false,
861+ "asc": true,
862+ "nulls": "last"
863+ }
864+ ],
865+ "isUnique": false,
866+ "concurrently": false,
867+ "method": "btree",
868+ "with": {}
869+ },
870+ "source_auth_bindings_workspace_idx": {
871+ "name": "source_auth_bindings_workspace_idx",
872+ "columns": [
873+ {
874+ "expression": "workspace_id",
875+ "isExpression": false,
876+ "asc": true,
877+ "nulls": "last"
878+ }
879+ ],
880+ "isUnique": false,
881+ "concurrently": false,
882+ "method": "btree",
883+ "with": {}
884+ },
885+ "source_auth_bindings_account_idx": {
886+ "name": "source_auth_bindings_account_idx",
887+ "columns": [
888+ {
889+ "expression": "account_id",
890+ "isExpression": false,
891+ "asc": true,
892+ "nulls": "last"
893+ }
894+ ],
895+ "isUnique": false,
896+ "concurrently": false,
897+ "method": "btree",
898+ "with": {}
899+ }
900+ },
901+ "foreignKeys": {},
902+ "compositePrimaryKeys": {},
903+ "uniqueConstraints": {},
904+ "policies": {},
905+ "checkConstraints": {},
906+ "isRLSEnabled": false
907+ },
908+ "public.sources": {
909+ "name": "sources",
910+ "schema": "",
911+ "columns": {
912+ "workspace_id": {
913+ "name": "workspace_id",
914+ "type": "text",
915+ "primaryKey": false,
916+ "notNull": true
917+ },
918+ "source_id": {
919+ "name": "source_id",
920+ "type": "text",
921+ "primaryKey": false,
922+ "notNull": true
923+ },
924+ "name": {
925+ "name": "name",
926+ "type": "text",
927+ "primaryKey": false,
928+ "notNull": true
929+ },
930+ "kind": {
931+ "name": "kind",
932+ "type": "text",
933+ "primaryKey": false,
934+ "notNull": true
935+ },
936+ "endpoint": {
937+ "name": "endpoint",
938+ "type": "text",
939+ "primaryKey": false,
940+ "notNull": true
941+ },
942+ "status": {
943+ "name": "status",
944+ "type": "text",
945+ "primaryKey": false,
946+ "notNull": true
947+ },
948+ "enabled": {
949+ "name": "enabled",
950+ "type": "boolean",
951+ "primaryKey": false,
952+ "notNull": true
953+ },
954+ "config_json": {
955+ "name": "config_json",
956+ "type": "text",
957+ "primaryKey": false,
958+ "notNull": true
959+ },
960+ "source_hash": {
961+ "name": "source_hash",
962+ "type": "text",
963+ "primaryKey": false,
964+ "notNull": false
965+ },
966+ "last_error": {
967+ "name": "last_error",
968+ "type": "text",
969+ "primaryKey": false,
970+ "notNull": false
971+ },
972+ "created_at": {
973+ "name": "created_at",
974+ "type": "bigint",
975+ "primaryKey": false,
976+ "notNull": true
977+ },
978+ "updated_at": {
979+ "name": "updated_at",
980+ "type": "bigint",
981+ "primaryKey": false,
982+ "notNull": true
983+ }
984+ },
985+ "indexes": {
986+ "sources_workspace_name_idx": {
987+ "name": "sources_workspace_name_idx",
988+ "columns": [
989+ {
990+ "expression": "workspace_id",
991+ "isExpression": false,
992+ "asc": true,
993+ "nulls": "last"
994+ },
995+ {
996+ "expression": "name",
997+ "isExpression": false,
998+ "asc": true,
999+ "nulls": "last"
1000+ }
1001+ ],
1002+ "isUnique": false,
1003+ "concurrently": false,
1004+ "method": "btree",
1005+ "with": {}
1006+ }
1007+ },
1008+ "foreignKeys": {},
1009+ "compositePrimaryKeys": {
1010+ "sources_workspace_id_source_id_pk": {
1011+ "name": "sources_workspace_id_source_id_pk",
1012+ "columns": [
1013+ "workspace_id",
1014+ "source_id"
1015+ ]
1016+ }
1017+ },
1018+ "uniqueConstraints": {},
1019+ "policies": {},
1020+ "checkConstraints": {},
1021+ "isRLSEnabled": false
1022+ },
1023+ "public.storage_instances": {
1024+ "name": "storage_instances",
1025+ "schema": "",
1026+ "columns": {
1027+ "id": {
1028+ "name": "id",
1029+ "type": "text",
1030+ "primaryKey": true,
1031+ "notNull": true
1032+ },
1033+ "scope_type": {
1034+ "name": "scope_type",
1035+ "type": "text",
1036+ "primaryKey": false,
1037+ "notNull": true
1038+ },
1039+ "durability": {
1040+ "name": "durability",
1041+ "type": "text",
1042+ "primaryKey": false,
1043+ "notNull": true
1044+ },
1045+ "status": {
1046+ "name": "status",
1047+ "type": "text",
1048+ "primaryKey": false,
1049+ "notNull": true
1050+ },
1051+ "provider": {
1052+ "name": "provider",
1053+ "type": "text",
1054+ "primaryKey": false,
1055+ "notNull": true
1056+ },
1057+ "backend_key": {
1058+ "name": "backend_key",
1059+ "type": "text",
1060+ "primaryKey": false,
1061+ "notNull": true
1062+ },
1063+ "organization_id": {
1064+ "name": "organization_id",
1065+ "type": "text",
1066+ "primaryKey": false,
1067+ "notNull": true
1068+ },
1069+ "workspace_id": {
1070+ "name": "workspace_id",
1071+ "type": "text",
1072+ "primaryKey": false,
1073+ "notNull": false
1074+ },
1075+ "account_id": {
1076+ "name": "account_id",
1077+ "type": "text",
1078+ "primaryKey": false,
1079+ "notNull": false
1080+ },
1081+ "created_by_account_id": {
1082+ "name": "created_by_account_id",
1083+ "type": "text",
1084+ "primaryKey": false,
1085+ "notNull": false
1086+ },
1087+ "purpose": {
1088+ "name": "purpose",
1089+ "type": "text",
1090+ "primaryKey": false,
1091+ "notNull": false
1092+ },
1093+ "size_bytes": {
1094+ "name": "size_bytes",
1095+ "type": "bigint",
1096+ "primaryKey": false,
1097+ "notNull": false
1098+ },
1099+ "file_count": {
1100+ "name": "file_count",
1101+ "type": "bigint",
1102+ "primaryKey": false,
1103+ "notNull": false
1104+ },
1105+ "created_at": {
1106+ "name": "created_at",
1107+ "type": "bigint",
1108+ "primaryKey": false,
1109+ "notNull": true
1110+ },
1111+ "updated_at": {
1112+ "name": "updated_at",
1113+ "type": "bigint",
1114+ "primaryKey": false,
1115+ "notNull": true
1116+ },
1117+ "last_seen_at": {
1118+ "name": "last_seen_at",
1119+ "type": "bigint",
1120+ "primaryKey": false,
1121+ "notNull": true
1122+ },
1123+ "closed_at": {
1124+ "name": "closed_at",
1125+ "type": "bigint",
1126+ "primaryKey": false,
1127+ "notNull": false
1128+ },
1129+ "expires_at": {
1130+ "name": "expires_at",
1131+ "type": "bigint",
1132+ "primaryKey": false,
1133+ "notNull": false
1134+ }
1135+ },
1136+ "indexes": {
1137+ "storage_instances_org_idx": {
1138+ "name": "storage_instances_org_idx",
1139+ "columns": [
1140+ {
1141+ "expression": "organization_id",
1142+ "isExpression": false,
1143+ "asc": true,
1144+ "nulls": "last"
1145+ }
1146+ ],
1147+ "isUnique": false,
1148+ "concurrently": false,
1149+ "method": "btree",
1150+ "with": {}
1151+ },
1152+ "storage_instances_workspace_idx": {
1153+ "name": "storage_instances_workspace_idx",
1154+ "columns": [
1155+ {
1156+ "expression": "workspace_id",
1157+ "isExpression": false,
1158+ "asc": true,
1159+ "nulls": "last"
1160+ }
1161+ ],
1162+ "isUnique": false,
1163+ "concurrently": false,
1164+ "method": "btree",
1165+ "with": {}
1166+ }
1167+ },
1168+ "foreignKeys": {},
1169+ "compositePrimaryKeys": {},
1170+ "uniqueConstraints": {},
1171+ "policies": {},
1172+ "checkConstraints": {},
1173+ "isRLSEnabled": false
1174+ },
1175+ "public.sync_states": {
1176+ "name": "sync_states",
1177+ "schema": "",
1178+ "columns": {
1179+ "id": {
1180+ "name": "id",
1181+ "type": "text",
1182+ "primaryKey": true,
1183+ "notNull": true
1184+ },
1185+ "workspace_id": {
1186+ "name": "workspace_id",
1187+ "type": "text",
1188+ "primaryKey": false,
1189+ "notNull": true
1190+ },
1191+ "target": {
1192+ "name": "target",
1193+ "type": "text",
1194+ "primaryKey": false,
1195+ "notNull": true
1196+ },
1197+ "target_url": {
1198+ "name": "target_url",
1199+ "type": "text",
1200+ "primaryKey": false,
1201+ "notNull": true
1202+ },
1203+ "linked_subject": {
1204+ "name": "linked_subject",
1205+ "type": "text",
1206+ "primaryKey": false,
1207+ "notNull": false
1208+ },
1209+ "cursor": {
1210+ "name": "cursor",
1211+ "type": "text",
1212+ "primaryKey": false,
1213+ "notNull": false
1214+ },
1215+ "last_sync_at": {
1216+ "name": "last_sync_at",
1217+ "type": "bigint",
1218+ "primaryKey": false,
1219+ "notNull": false
1220+ },
1221+ "updated_at": {
1222+ "name": "updated_at",
1223+ "type": "bigint",
1224+ "primaryKey": false,
1225+ "notNull": true
1226+ }
1227+ },
1228+ "indexes": {
1229+ "sync_states_workspace_idx": {
1230+ "name": "sync_states_workspace_idx",
1231+ "columns": [
1232+ {
1233+ "expression": "workspace_id",
1234+ "isExpression": false,
1235+ "asc": true,
1236+ "nulls": "last"
1237+ }
1238+ ],
1239+ "isUnique": false,
1240+ "concurrently": false,
1241+ "method": "btree",
1242+ "with": {}
1243+ }
1244+ },
1245+ "foreignKeys": {},
1246+ "compositePrimaryKeys": {},
1247+ "uniqueConstraints": {},
1248+ "policies": {},
1249+ "checkConstraints": {},
1250+ "isRLSEnabled": false
1251+ },
1252+ "public.task_runs": {
1253+ "name": "task_runs",
1254+ "schema": "",
1255+ "columns": {
1256+ "id": {
1257+ "name": "id",
1258+ "type": "text",
1259+ "primaryKey": true,
1260+ "notNull": true
1261+ },
1262+ "workspace_id": {
1263+ "name": "workspace_id",
1264+ "type": "text",
1265+ "primaryKey": false,
1266+ "notNull": true
1267+ },
1268+ "account_id": {
1269+ "name": "account_id",
1270+ "type": "text",
1271+ "primaryKey": false,
1272+ "notNull": true
1273+ },
1274+ "session_id": {
1275+ "name": "session_id",
1276+ "type": "text",
1277+ "primaryKey": false,
1278+ "notNull": true
1279+ },
1280+ "runtime_id": {
1281+ "name": "runtime_id",
1282+ "type": "text",
1283+ "primaryKey": false,
1284+ "notNull": true
1285+ },
1286+ "code_hash": {
1287+ "name": "code_hash",
1288+ "type": "text",
1289+ "primaryKey": false,
1290+ "notNull": true
1291+ },
1292+ "status": {
1293+ "name": "status",
1294+ "type": "text",
1295+ "primaryKey": false,
1296+ "notNull": true
1297+ },
1298+ "started_at": {
1299+ "name": "started_at",
1300+ "type": "bigint",
1301+ "primaryKey": false,
1302+ "notNull": false
1303+ },
1304+ "completed_at": {
1305+ "name": "completed_at",
1306+ "type": "bigint",
1307+ "primaryKey": false,
1308+ "notNull": false
1309+ },
1310+ "exit_code": {
1311+ "name": "exit_code",
1312+ "type": "bigint",
1313+ "primaryKey": false,
1314+ "notNull": false
1315+ },
1316+ "error": {
1317+ "name": "error",
1318+ "type": "text",
1319+ "primaryKey": false,
1320+ "notNull": false
1321+ }
1322+ },
1323+ "indexes": {
1324+ "task_runs_workspace_idx": {
1325+ "name": "task_runs_workspace_idx",
1326+ "columns": [
1327+ {
1328+ "expression": "workspace_id",
1329+ "isExpression": false,
1330+ "asc": true,
1331+ "nulls": "last"
1332+ }
1333+ ],
1334+ "isUnique": false,
1335+ "concurrently": false,
1336+ "method": "btree",
1337+ "with": {}
1338+ }
1339+ },
1340+ "foreignKeys": {},
1341+ "compositePrimaryKeys": {},
1342+ "uniqueConstraints": {},
1343+ "policies": {},
1344+ "checkConstraints": {},
1345+ "isRLSEnabled": false
1346+ },
1347+ "public.tool_artifacts": {
1348+ "name": "tool_artifacts",
1349+ "schema": "",
1350+ "columns": {
1351+ "id": {
1352+ "name": "id",
1353+ "type": "text",
1354+ "primaryKey": false,
1355+ "notNull": true
1356+ },
1357+ "workspace_id": {
1358+ "name": "workspace_id",
1359+ "type": "text",
1360+ "primaryKey": false,
1361+ "notNull": true
1362+ },
1363+ "source_id": {
1364+ "name": "source_id",
1365+ "type": "text",
1366+ "primaryKey": false,
1367+ "notNull": true
1368+ },
1369+ "source_hash": {
1370+ "name": "source_hash",
1371+ "type": "text",
1372+ "primaryKey": false,
1373+ "notNull": true
1374+ },
1375+ "tool_count": {
1376+ "name": "tool_count",
1377+ "type": "bigint",
1378+ "primaryKey": false,
1379+ "notNull": true
1380+ },
1381+ "manifest_json": {
1382+ "name": "manifest_json",
1383+ "type": "text",
1384+ "primaryKey": false,
1385+ "notNull": true
1386+ },
1387+ "created_at": {
1388+ "name": "created_at",
1389+ "type": "bigint",
1390+ "primaryKey": false,
1391+ "notNull": true
1392+ },
1393+ "updated_at": {
1394+ "name": "updated_at",
1395+ "type": "bigint",
1396+ "primaryKey": false,
1397+ "notNull": true
1398+ }
1399+ },
1400+ "indexes": {
1401+ "tool_artifacts_id_idx": {
1402+ "name": "tool_artifacts_id_idx",
1403+ "columns": [
1404+ {
1405+ "expression": "id",
1406+ "isExpression": false,
1407+ "asc": true,
1408+ "nulls": "last"
1409+ }
1410+ ],
1411+ "isUnique": true,
1412+ "concurrently": false,
1413+ "method": "btree",
1414+ "with": {}
1415+ }
1416+ },
1417+ "foreignKeys": {},
1418+ "compositePrimaryKeys": {
1419+ "tool_artifacts_workspace_id_source_id_pk": {
1420+ "name": "tool_artifacts_workspace_id_source_id_pk",
1421+ "columns": [
1422+ "workspace_id",
1423+ "source_id"
1424+ ]
1425+ }
1426+ },
1427+ "uniqueConstraints": {},
1428+ "policies": {},
1429+ "checkConstraints": {},
1430+ "isRLSEnabled": false
1431+ },
1432+ "public.workspaces": {
1433+ "name": "workspaces",
1434+ "schema": "",
1435+ "columns": {
1436+ "id": {
1437+ "name": "id",
1438+ "type": "text",
1439+ "primaryKey": true,
1440+ "notNull": true
1441+ },
1442+ "organization_id": {
1443+ "name": "organization_id",
1444+ "type": "text",
1445+ "primaryKey": false,
1446+ "notNull": true
1447+ },
1448+ "name": {
1449+ "name": "name",
1450+ "type": "text",
1451+ "primaryKey": false,
1452+ "notNull": true
1453+ },
1454+ "created_by_account_id": {
1455+ "name": "created_by_account_id",
1456+ "type": "text",
1457+ "primaryKey": false,
1458+ "notNull": false
1459+ },
1460+ "created_at": {
1461+ "name": "created_at",
1462+ "type": "bigint",
1463+ "primaryKey": false,
1464+ "notNull": true
1465+ },
1466+ "updated_at": {
1467+ "name": "updated_at",
1468+ "type": "bigint",
1469+ "primaryKey": false,
1470+ "notNull": true
1471+ }
1472+ },
1473+ "indexes": {
1474+ "workspaces_org_idx": {
1475+ "name": "workspaces_org_idx",
1476+ "columns": [
1477+ {
1478+ "expression": "organization_id",
1479+ "isExpression": false,
1480+ "asc": true,
1481+ "nulls": "last"
1482+ }
1483+ ],
1484+ "isUnique": false,
1485+ "concurrently": false,
1486+ "method": "btree",
1487+ "with": {}
1488+ }
1489+ },
1490+ "foreignKeys": {},
1491+ "compositePrimaryKeys": {},
1492+ "uniqueConstraints": {},
1493+ "policies": {},
1494+ "checkConstraints": {},
1495+ "isRLSEnabled": false
1496+ }
1497+ },
1498+ "enums": {},
1499+ "schemas": {},
1500+ "sequences": {},
1501+ "roles": {},
1502+ "policies": {},
1503+ "views": {},
1504+ "_meta": {
1505+ "columns": {},
1506+ "schemas": {},
1507+ "tables": {}
1508+ }
1509+}
packages/persistence-sql/drizzle/postgres/meta/_journal.json+13−0
@@ -0,0 +1,13 @@
1+{
2+ "version": "7",
3+ "dialect": "postgresql",
4+ "entries": [
5+ {
6+ "idx": 0,
7+ "version": "7",
8+ "when": 1772506152805,
9+ "tag": "0000_spicy_barracuda",
10+ "breakpoints": true
11+ }
12+ ]
13+}
packages/persistence-sql/drizzle/sqlite/0000_curved_raider.sql+224−0
@@ -0,0 +1,224 @@
1+CREATE TABLE `approvals` (
2+ `id` text PRIMARY KEY NOT NULL,
3+ `workspace_id` text NOT NULL,
4+ `task_run_id` text NOT NULL,
5+ `call_id` text NOT NULL,
6+ `tool_path` text NOT NULL,
7+ `status` text NOT NULL,
8+ `input_preview_json` text NOT NULL,
9+ `reason` text,
10+ `requested_at` integer NOT NULL,
11+ `resolved_at` integer
12+);
13+--> statement-breakpoint
14+CREATE INDEX `approvals_workspace_idx` ON `approvals` (`workspace_id`);--> statement-breakpoint
15+CREATE INDEX `approvals_task_run_idx` ON `approvals` (`task_run_id`);--> statement-breakpoint
16+CREATE TABLE `auth_connections` (
17+ `id` text PRIMARY KEY NOT NULL,
18+ `organization_id` text NOT NULL,
19+ `workspace_id` text,
20+ `account_id` text,
21+ `owner_type` text NOT NULL,
22+ `strategy` text NOT NULL,
23+ `display_name` text NOT NULL,
24+ `status` text NOT NULL,
25+ `status_reason` text,
26+ `last_auth_error_class` text,
27+ `metadata_json` text,
28+ `additional_headers_json` text,
29+ `created_by_account_id` text,
30+ `created_at` integer NOT NULL,
31+ `updated_at` integer NOT NULL,
32+ `last_used_at` integer
33+);
34+--> statement-breakpoint
35+CREATE INDEX `auth_connections_org_idx` ON `auth_connections` (`organization_id`);--> statement-breakpoint
36+CREATE INDEX `auth_connections_workspace_idx` ON `auth_connections` (`workspace_id`);--> statement-breakpoint
37+CREATE INDEX `auth_connections_account_idx` ON `auth_connections` (`account_id`);--> statement-breakpoint
38+CREATE TABLE `auth_materials` (
39+ `id` text PRIMARY KEY NOT NULL,
40+ `connection_id` text NOT NULL,
41+ `ciphertext` text NOT NULL,
42+ `key_version` text NOT NULL,
43+ `created_at` integer NOT NULL,
44+ `updated_at` integer NOT NULL
45+);
46+--> statement-breakpoint
47+CREATE INDEX `auth_materials_connection_idx` ON `auth_materials` (`connection_id`);--> statement-breakpoint
48+CREATE TABLE `oauth_states` (
49+ `id` text PRIMARY KEY NOT NULL,
50+ `connection_id` text NOT NULL,
51+ `access_token_ciphertext` text NOT NULL,
52+ `refresh_token_ciphertext` text,
53+ `key_version` text NOT NULL,
54+ `expires_at` integer,
55+ `scope` text,
56+ `token_type` text,
57+ `issuer` text,
58+ `refresh_config_json` text,
59+ `token_version` integer NOT NULL,
60+ `lease_holder` text,
61+ `lease_expires_at` integer,
62+ `lease_fence` integer NOT NULL,
63+ `last_refresh_at` integer,
64+ `last_refresh_error_class` text,
65+ `last_refresh_error` text,
66+ `reauth_required_at` integer,
67+ `created_at` integer NOT NULL,
68+ `updated_at` integer NOT NULL
69+);
70+--> statement-breakpoint
71+CREATE INDEX `oauth_states_connection_idx` ON `oauth_states` (`connection_id`);--> statement-breakpoint
72+CREATE TABLE `organization_memberships` (
73+ `id` text PRIMARY KEY NOT NULL,
74+ `organization_id` text NOT NULL,
75+ `account_id` text NOT NULL,
76+ `role` text NOT NULL,
77+ `status` text NOT NULL,
78+ `billable` integer NOT NULL,
79+ `invited_by_account_id` text,
80+ `joined_at` integer,
81+ `created_at` integer NOT NULL,
82+ `updated_at` integer NOT NULL
83+);
84+--> statement-breakpoint
85+CREATE INDEX `organization_memberships_org_idx` ON `organization_memberships` (`organization_id`);--> statement-breakpoint
86+CREATE INDEX `organization_memberships_account_idx` ON `organization_memberships` (`account_id`);--> statement-breakpoint
87+CREATE TABLE `organizations` (
88+ `id` text PRIMARY KEY NOT NULL,
89+ `slug` text NOT NULL,
90+ `name` text NOT NULL,
91+ `status` text NOT NULL,
92+ `created_by_account_id` text,
93+ `created_at` integer NOT NULL,
94+ `updated_at` integer NOT NULL
95+);
96+--> statement-breakpoint
97+CREATE TABLE `policies` (
98+ `id` text PRIMARY KEY NOT NULL,
99+ `workspace_id` text NOT NULL,
100+ `tool_path_pattern` text NOT NULL,
101+ `decision` text NOT NULL,
102+ `created_at` integer NOT NULL,
103+ `updated_at` integer NOT NULL
104+);
105+--> statement-breakpoint
106+CREATE INDEX `policies_workspace_idx` ON `policies` (`workspace_id`);--> statement-breakpoint
107+CREATE TABLE `profile` (
108+ `id` text PRIMARY KEY NOT NULL,
109+ `default_workspace_id` text,
110+ `display_name` text NOT NULL,
111+ `runtime_mode` text NOT NULL,
112+ `created_at` integer NOT NULL,
113+ `updated_at` integer NOT NULL
114+);
115+--> statement-breakpoint
116+CREATE TABLE `source_auth_bindings` (
117+ `id` text PRIMARY KEY NOT NULL,
118+ `source_id` text NOT NULL,
119+ `connection_id` text NOT NULL,
120+ `organization_id` text NOT NULL,
121+ `workspace_id` text,
122+ `account_id` text,
123+ `scope_type` text NOT NULL,
124+ `selector` text,
125+ `enabled` integer NOT NULL,
126+ `created_at` integer NOT NULL,
127+ `updated_at` integer NOT NULL
128+);
129+--> statement-breakpoint
130+CREATE INDEX `source_auth_bindings_source_idx` ON `source_auth_bindings` (`source_id`);--> statement-breakpoint
131+CREATE INDEX `source_auth_bindings_connection_idx` ON `source_auth_bindings` (`connection_id`);--> statement-breakpoint
132+CREATE INDEX `source_auth_bindings_org_idx` ON `source_auth_bindings` (`organization_id`);--> statement-breakpoint
133+CREATE INDEX `source_auth_bindings_workspace_idx` ON `source_auth_bindings` (`workspace_id`);--> statement-breakpoint
134+CREATE INDEX `source_auth_bindings_account_idx` ON `source_auth_bindings` (`account_id`);--> statement-breakpoint
135+CREATE TABLE `sources` (
136+ `workspace_id` text NOT NULL,
137+ `source_id` text NOT NULL,
138+ `name` text NOT NULL,
139+ `kind` text NOT NULL,
140+ `endpoint` text NOT NULL,
141+ `status` text NOT NULL,
142+ `enabled` integer NOT NULL,
143+ `config_json` text NOT NULL,
144+ `source_hash` text,
145+ `last_error` text,
146+ `created_at` integer NOT NULL,
147+ `updated_at` integer NOT NULL,
148+ PRIMARY KEY(`workspace_id`, `source_id`)
149+);
150+--> statement-breakpoint
151+CREATE INDEX `sources_workspace_name_idx` ON `sources` (`workspace_id`,`name`);--> statement-breakpoint
152+CREATE TABLE `storage_instances` (
153+ `id` text PRIMARY KEY NOT NULL,
154+ `scope_type` text NOT NULL,
155+ `durability` text NOT NULL,
156+ `status` text NOT NULL,
157+ `provider` text NOT NULL,
158+ `backend_key` text NOT NULL,
159+ `organization_id` text NOT NULL,
160+ `workspace_id` text,
161+ `account_id` text,
162+ `created_by_account_id` text,
163+ `purpose` text,
164+ `size_bytes` integer,
165+ `file_count` integer,
166+ `created_at` integer NOT NULL,
167+ `updated_at` integer NOT NULL,
168+ `last_seen_at` integer NOT NULL,
169+ `closed_at` integer,
170+ `expires_at` integer
171+);
172+--> statement-breakpoint
173+CREATE INDEX `storage_instances_org_idx` ON `storage_instances` (`organization_id`);--> statement-breakpoint
174+CREATE INDEX `storage_instances_workspace_idx` ON `storage_instances` (`workspace_id`);--> statement-breakpoint
175+CREATE TABLE `sync_states` (
176+ `id` text PRIMARY KEY NOT NULL,
177+ `workspace_id` text NOT NULL,
178+ `target` text NOT NULL,
179+ `target_url` text NOT NULL,
180+ `linked_subject` text,
181+ `cursor` text,
182+ `last_sync_at` integer,
183+ `updated_at` integer NOT NULL
184+);
185+--> statement-breakpoint
186+CREATE INDEX `sync_states_workspace_idx` ON `sync_states` (`workspace_id`);--> statement-breakpoint
187+CREATE TABLE `task_runs` (
188+ `id` text PRIMARY KEY NOT NULL,
189+ `workspace_id` text NOT NULL,
190+ `account_id` text NOT NULL,
191+ `session_id` text NOT NULL,
192+ `runtime_id` text NOT NULL,
193+ `code_hash` text NOT NULL,
194+ `status` text NOT NULL,
195+ `started_at` integer,
196+ `completed_at` integer,
197+ `exit_code` integer,
198+ `error` text
199+);
200+--> statement-breakpoint
201+CREATE INDEX `task_runs_workspace_idx` ON `task_runs` (`workspace_id`);--> statement-breakpoint
202+CREATE TABLE `tool_artifacts` (
203+ `id` text NOT NULL,
204+ `workspace_id` text NOT NULL,
205+ `source_id` text NOT NULL,
206+ `source_hash` text NOT NULL,
207+ `tool_count` integer NOT NULL,
208+ `manifest_json` text NOT NULL,
209+ `created_at` integer NOT NULL,
210+ `updated_at` integer NOT NULL,
211+ PRIMARY KEY(`workspace_id`, `source_id`)
212+);
213+--> statement-breakpoint
214+CREATE UNIQUE INDEX `tool_artifacts_id_idx` ON `tool_artifacts` (`id`);--> statement-breakpoint
215+CREATE TABLE `workspaces` (
216+ `id` text PRIMARY KEY NOT NULL,
217+ `organization_id` text NOT NULL,
218+ `name` text NOT NULL,
219+ `created_by_account_id` text,
220+ `created_at` integer NOT NULL,
221+ `updated_at` integer NOT NULL
222+);
223+--> statement-breakpoint
224+CREATE INDEX `workspaces_org_idx` ON `workspaces` (`organization_id`);
packages/persistence-sql/drizzle/sqlite/meta/0000_snapshot.json+1437−0
@@ -0,0 +1,1437 @@
1+{
2+ "version": "6",
3+ "dialect": "sqlite",
4+ "id": "012495d1-d78e-4f31-a64f-7328fdf970c0",
5+ "prevId": "00000000-0000-0000-0000-000000000000",
6+ "tables": {
7+ "approvals": {
8+ "name": "approvals",
9+ "columns": {
10+ "id": {
11+ "name": "id",
12+ "type": "text",
13+ "primaryKey": true,
14+ "notNull": true,
15+ "autoincrement": false
16+ },
17+ "workspace_id": {
18+ "name": "workspace_id",
19+ "type": "text",
20+ "primaryKey": false,
21+ "notNull": true,
22+ "autoincrement": false
23+ },
24+ "task_run_id": {
25+ "name": "task_run_id",
26+ "type": "text",
27+ "primaryKey": false,
28+ "notNull": true,
29+ "autoincrement": false
30+ },
31+ "call_id": {
32+ "name": "call_id",
33+ "type": "text",
34+ "primaryKey": false,
35+ "notNull": true,
36+ "autoincrement": false
37+ },
38+ "tool_path": {
39+ "name": "tool_path",
40+ "type": "text",
41+ "primaryKey": false,
42+ "notNull": true,
43+ "autoincrement": false
44+ },
45+ "status": {
46+ "name": "status",
47+ "type": "text",
48+ "primaryKey": false,
49+ "notNull": true,
50+ "autoincrement": false
51+ },
52+ "input_preview_json": {
53+ "name": "input_preview_json",
54+ "type": "text",
55+ "primaryKey": false,
56+ "notNull": true,
57+ "autoincrement": false
58+ },
59+ "reason": {
60+ "name": "reason",
61+ "type": "text",
62+ "primaryKey": false,
63+ "notNull": false,
64+ "autoincrement": false
65+ },
66+ "requested_at": {
67+ "name": "requested_at",
68+ "type": "integer",
69+ "primaryKey": false,
70+ "notNull": true,
71+ "autoincrement": false
72+ },
73+ "resolved_at": {
74+ "name": "resolved_at",
75+ "type": "integer",
76+ "primaryKey": false,
77+ "notNull": false,
78+ "autoincrement": false
79+ }
80+ },
81+ "indexes": {
82+ "approvals_workspace_idx": {
83+ "name": "approvals_workspace_idx",
84+ "columns": [
85+ "workspace_id"
86+ ],
87+ "isUnique": false
88+ },
89+ "approvals_task_run_idx": {
90+ "name": "approvals_task_run_idx",
91+ "columns": [
92+ "task_run_id"
93+ ],
94+ "isUnique": false
95+ }
96+ },
97+ "foreignKeys": {},
98+ "compositePrimaryKeys": {},
99+ "uniqueConstraints": {},
100+ "checkConstraints": {}
101+ },
102+ "auth_connections": {
103+ "name": "auth_connections",
104+ "columns": {
105+ "id": {
106+ "name": "id",
107+ "type": "text",
108+ "primaryKey": true,
109+ "notNull": true,
110+ "autoincrement": false
111+ },
112+ "organization_id": {
113+ "name": "organization_id",
114+ "type": "text",
115+ "primaryKey": false,
116+ "notNull": true,
117+ "autoincrement": false
118+ },
119+ "workspace_id": {
120+ "name": "workspace_id",
121+ "type": "text",
122+ "primaryKey": false,
123+ "notNull": false,
124+ "autoincrement": false
125+ },
126+ "account_id": {
127+ "name": "account_id",
128+ "type": "text",
129+ "primaryKey": false,
130+ "notNull": false,
131+ "autoincrement": false
132+ },
133+ "owner_type": {
134+ "name": "owner_type",
135+ "type": "text",
136+ "primaryKey": false,
137+ "notNull": true,
138+ "autoincrement": false
139+ },
140+ "strategy": {
141+ "name": "strategy",
142+ "type": "text",
143+ "primaryKey": false,
144+ "notNull": true,
145+ "autoincrement": false
146+ },
147+ "display_name": {
148+ "name": "display_name",
149+ "type": "text",
150+ "primaryKey": false,
151+ "notNull": true,
152+ "autoincrement": false
153+ },
154+ "status": {
155+ "name": "status",
156+ "type": "text",
157+ "primaryKey": false,
158+ "notNull": true,
159+ "autoincrement": false
160+ },
161+ "status_reason": {
162+ "name": "status_reason",
163+ "type": "text",
164+ "primaryKey": false,
165+ "notNull": false,
166+ "autoincrement": false
167+ },
168+ "last_auth_error_class": {
169+ "name": "last_auth_error_class",
170+ "type": "text",
171+ "primaryKey": false,
172+ "notNull": false,
173+ "autoincrement": false
174+ },
175+ "metadata_json": {
176+ "name": "metadata_json",
177+ "type": "text",
178+ "primaryKey": false,
179+ "notNull": false,
180+ "autoincrement": false
181+ },
182+ "additional_headers_json": {
183+ "name": "additional_headers_json",
184+ "type": "text",
185+ "primaryKey": false,
186+ "notNull": false,
187+ "autoincrement": false
188+ },
189+ "created_by_account_id": {
190+ "name": "created_by_account_id",
191+ "type": "text",
192+ "primaryKey": false,
193+ "notNull": false,
194+ "autoincrement": false
195+ },
196+ "created_at": {
197+ "name": "created_at",
198+ "type": "integer",
199+ "primaryKey": false,
200+ "notNull": true,
201+ "autoincrement": false
202+ },
203+ "updated_at": {
204+ "name": "updated_at",
205+ "type": "integer",
206+ "primaryKey": false,
207+ "notNull": true,
208+ "autoincrement": false
209+ },
210+ "last_used_at": {
211+ "name": "last_used_at",
212+ "type": "integer",
213+ "primaryKey": false,
214+ "notNull": false,
215+ "autoincrement": false
216+ }
217+ },
218+ "indexes": {
219+ "auth_connections_org_idx": {
220+ "name": "auth_connections_org_idx",
221+ "columns": [
222+ "organization_id"
223+ ],
224+ "isUnique": false
225+ },
226+ "auth_connections_workspace_idx": {
227+ "name": "auth_connections_workspace_idx",
228+ "columns": [
229+ "workspace_id"
230+ ],
231+ "isUnique": false
232+ },
233+ "auth_connections_account_idx": {
234+ "name": "auth_connections_account_idx",
235+ "columns": [
236+ "account_id"
237+ ],
238+ "isUnique": false
239+ }
240+ },
241+ "foreignKeys": {},
242+ "compositePrimaryKeys": {},
243+ "uniqueConstraints": {},
244+ "checkConstraints": {}
245+ },
246+ "auth_materials": {
247+ "name": "auth_materials",
248+ "columns": {
249+ "id": {
250+ "name": "id",
251+ "type": "text",
252+ "primaryKey": true,
253+ "notNull": true,
254+ "autoincrement": false
255+ },
256+ "connection_id": {
257+ "name": "connection_id",
258+ "type": "text",
259+ "primaryKey": false,
260+ "notNull": true,
261+ "autoincrement": false
262+ },
263+ "ciphertext": {
264+ "name": "ciphertext",
265+ "type": "text",
266+ "primaryKey": false,
267+ "notNull": true,
268+ "autoincrement": false
269+ },
270+ "key_version": {
271+ "name": "key_version",
272+ "type": "text",
273+ "primaryKey": false,
274+ "notNull": true,
275+ "autoincrement": false
276+ },
277+ "created_at": {
278+ "name": "created_at",
279+ "type": "integer",
280+ "primaryKey": false,
281+ "notNull": true,
282+ "autoincrement": false
283+ },
284+ "updated_at": {
285+ "name": "updated_at",
286+ "type": "integer",
287+ "primaryKey": false,
288+ "notNull": true,
289+ "autoincrement": false
290+ }
291+ },
292+ "indexes": {
293+ "auth_materials_connection_idx": {
294+ "name": "auth_materials_connection_idx",
295+ "columns": [
296+ "connection_id"
297+ ],
298+ "isUnique": false
299+ }
300+ },
301+ "foreignKeys": {},
302+ "compositePrimaryKeys": {},
303+ "uniqueConstraints": {},
304+ "checkConstraints": {}
305+ },
306+ "oauth_states": {
307+ "name": "oauth_states",
308+ "columns": {
309+ "id": {
310+ "name": "id",
311+ "type": "text",
312+ "primaryKey": true,
313+ "notNull": true,
314+ "autoincrement": false
315+ },
316+ "connection_id": {
317+ "name": "connection_id",
318+ "type": "text",
319+ "primaryKey": false,
320+ "notNull": true,
321+ "autoincrement": false
322+ },
323+ "access_token_ciphertext": {
324+ "name": "access_token_ciphertext",
325+ "type": "text",
326+ "primaryKey": false,
327+ "notNull": true,
328+ "autoincrement": false
329+ },
330+ "refresh_token_ciphertext": {
331+ "name": "refresh_token_ciphertext",
332+ "type": "text",
333+ "primaryKey": false,
334+ "notNull": false,
335+ "autoincrement": false
336+ },
337+ "key_version": {
338+ "name": "key_version",
339+ "type": "text",
340+ "primaryKey": false,
341+ "notNull": true,
342+ "autoincrement": false
343+ },
344+ "expires_at": {
345+ "name": "expires_at",
346+ "type": "integer",
347+ "primaryKey": false,
348+ "notNull": false,
349+ "autoincrement": false
350+ },
351+ "scope": {
352+ "name": "scope",
353+ "type": "text",
354+ "primaryKey": false,
355+ "notNull": false,
356+ "autoincrement": false
357+ },
358+ "token_type": {
359+ "name": "token_type",
360+ "type": "text",
361+ "primaryKey": false,
362+ "notNull": false,
363+ "autoincrement": false
364+ },
365+ "issuer": {
366+ "name": "issuer",
367+ "type": "text",
368+ "primaryKey": false,
369+ "notNull": false,
370+ "autoincrement": false
371+ },
372+ "refresh_config_json": {
373+ "name": "refresh_config_json",
374+ "type": "text",
375+ "primaryKey": false,
376+ "notNull": false,
377+ "autoincrement": false
378+ },
379+ "token_version": {
380+ "name": "token_version",
381+ "type": "integer",
382+ "primaryKey": false,
383+ "notNull": true,
384+ "autoincrement": false
385+ },
386+ "lease_holder": {
387+ "name": "lease_holder",
388+ "type": "text",
389+ "primaryKey": false,
390+ "notNull": false,
391+ "autoincrement": false
392+ },
393+ "lease_expires_at": {
394+ "name": "lease_expires_at",
395+ "type": "integer",
396+ "primaryKey": false,
397+ "notNull": false,
398+ "autoincrement": false
399+ },
400+ "lease_fence": {
401+ "name": "lease_fence",
402+ "type": "integer",
403+ "primaryKey": false,
404+ "notNull": true,
405+ "autoincrement": false
406+ },
407+ "last_refresh_at": {
408+ "name": "last_refresh_at",
409+ "type": "integer",
410+ "primaryKey": false,
411+ "notNull": false,
412+ "autoincrement": false
413+ },
414+ "last_refresh_error_class": {
415+ "name": "last_refresh_error_class",
416+ "type": "text",
417+ "primaryKey": false,
418+ "notNull": false,
419+ "autoincrement": false
420+ },
421+ "last_refresh_error": {
422+ "name": "last_refresh_error",
423+ "type": "text",
424+ "primaryKey": false,
425+ "notNull": false,
426+ "autoincrement": false
427+ },
428+ "reauth_required_at": {
429+ "name": "reauth_required_at",
430+ "type": "integer",
431+ "primaryKey": false,
432+ "notNull": false,
433+ "autoincrement": false
434+ },
435+ "created_at": {
436+ "name": "created_at",
437+ "type": "integer",
438+ "primaryKey": false,
439+ "notNull": true,
440+ "autoincrement": false
441+ },
442+ "updated_at": {
443+ "name": "updated_at",
444+ "type": "integer",
445+ "primaryKey": false,
446+ "notNull": true,
447+ "autoincrement": false
448+ }
449+ },
450+ "indexes": {
451+ "oauth_states_connection_idx": {
452+ "name": "oauth_states_connection_idx",
453+ "columns": [
454+ "connection_id"
455+ ],
456+ "isUnique": false
457+ }
458+ },
459+ "foreignKeys": {},
460+ "compositePrimaryKeys": {},
461+ "uniqueConstraints": {},
462+ "checkConstraints": {}
463+ },
464+ "organization_memberships": {
465+ "name": "organization_memberships",
466+ "columns": {
467+ "id": {
468+ "name": "id",
469+ "type": "text",
470+ "primaryKey": true,
471+ "notNull": true,
472+ "autoincrement": false
473+ },
474+ "organization_id": {
475+ "name": "organization_id",
476+ "type": "text",
477+ "primaryKey": false,
478+ "notNull": true,
479+ "autoincrement": false
480+ },
481+ "account_id": {
482+ "name": "account_id",
483+ "type": "text",
484+ "primaryKey": false,
485+ "notNull": true,
486+ "autoincrement": false
487+ },
488+ "role": {
489+ "name": "role",
490+ "type": "text",
491+ "primaryKey": false,
492+ "notNull": true,
493+ "autoincrement": false
494+ },
495+ "status": {
496+ "name": "status",
497+ "type": "text",
498+ "primaryKey": false,
499+ "notNull": true,
500+ "autoincrement": false
501+ },
502+ "billable": {
503+ "name": "billable",
504+ "type": "integer",
505+ "primaryKey": false,
506+ "notNull": true,
507+ "autoincrement": false
508+ },
509+ "invited_by_account_id": {
510+ "name": "invited_by_account_id",
511+ "type": "text",
512+ "primaryKey": false,
513+ "notNull": false,
514+ "autoincrement": false
515+ },
516+ "joined_at": {
517+ "name": "joined_at",
518+ "type": "integer",
519+ "primaryKey": false,
520+ "notNull": false,
521+ "autoincrement": false
522+ },
523+ "created_at": {
524+ "name": "created_at",
525+ "type": "integer",
526+ "primaryKey": false,
527+ "notNull": true,
528+ "autoincrement": false
529+ },
530+ "updated_at": {
531+ "name": "updated_at",
532+ "type": "integer",
533+ "primaryKey": false,
534+ "notNull": true,
535+ "autoincrement": false
536+ }
537+ },
538+ "indexes": {
539+ "organization_memberships_org_idx": {
540+ "name": "organization_memberships_org_idx",
541+ "columns": [
542+ "organization_id"
543+ ],
544+ "isUnique": false
545+ },
546+ "organization_memberships_account_idx": {
547+ "name": "organization_memberships_account_idx",
548+ "columns": [
549+ "account_id"
550+ ],
551+ "isUnique": false
552+ }
553+ },
554+ "foreignKeys": {},
555+ "compositePrimaryKeys": {},
556+ "uniqueConstraints": {},
557+ "checkConstraints": {}
558+ },
559+ "organizations": {
560+ "name": "organizations",
561+ "columns": {
562+ "id": {
563+ "name": "id",
564+ "type": "text",
565+ "primaryKey": true,
566+ "notNull": true,
567+ "autoincrement": false
568+ },
569+ "slug": {
570+ "name": "slug",
571+ "type": "text",
572+ "primaryKey": false,
573+ "notNull": true,
574+ "autoincrement": false
575+ },
576+ "name": {
577+ "name": "name",
578+ "type": "text",
579+ "primaryKey": false,
580+ "notNull": true,
581+ "autoincrement": false
582+ },
583+ "status": {
584+ "name": "status",
585+ "type": "text",
586+ "primaryKey": false,
587+ "notNull": true,
588+ "autoincrement": false
589+ },
590+ "created_by_account_id": {
591+ "name": "created_by_account_id",
592+ "type": "text",
593+ "primaryKey": false,
594+ "notNull": false,
595+ "autoincrement": false
596+ },
597+ "created_at": {
598+ "name": "created_at",
599+ "type": "integer",
600+ "primaryKey": false,
601+ "notNull": true,
602+ "autoincrement": false
603+ },
604+ "updated_at": {
605+ "name": "updated_at",
606+ "type": "integer",
607+ "primaryKey": false,
608+ "notNull": true,
609+ "autoincrement": false
610+ }
611+ },
612+ "indexes": {},
613+ "foreignKeys": {},
614+ "compositePrimaryKeys": {},
615+ "uniqueConstraints": {},
616+ "checkConstraints": {}
617+ },
618+ "policies": {
619+ "name": "policies",
620+ "columns": {
621+ "id": {
622+ "name": "id",
623+ "type": "text",
624+ "primaryKey": true,
625+ "notNull": true,
626+ "autoincrement": false
627+ },
628+ "workspace_id": {
629+ "name": "workspace_id",
630+ "type": "text",
631+ "primaryKey": false,
632+ "notNull": true,
633+ "autoincrement": false
634+ },
635+ "tool_path_pattern": {
636+ "name": "tool_path_pattern",
637+ "type": "text",
638+ "primaryKey": false,
639+ "notNull": true,
640+ "autoincrement": false
641+ },
642+ "decision": {
643+ "name": "decision",
644+ "type": "text",
645+ "primaryKey": false,
646+ "notNull": true,
647+ "autoincrement": false
648+ },
649+ "created_at": {
650+ "name": "created_at",
651+ "type": "integer",
652+ "primaryKey": false,
653+ "notNull": true,
654+ "autoincrement": false
655+ },
656+ "updated_at": {
657+ "name": "updated_at",
658+ "type": "integer",
659+ "primaryKey": false,
660+ "notNull": true,
661+ "autoincrement": false
662+ }
663+ },
664+ "indexes": {
665+ "policies_workspace_idx": {
666+ "name": "policies_workspace_idx",
667+ "columns": [
668+ "workspace_id"
669+ ],
670+ "isUnique": false
671+ }
672+ },
673+ "foreignKeys": {},
674+ "compositePrimaryKeys": {},
675+ "uniqueConstraints": {},
676+ "checkConstraints": {}
677+ },
678+ "profile": {
679+ "name": "profile",
680+ "columns": {
681+ "id": {
682+ "name": "id",
683+ "type": "text",
684+ "primaryKey": true,
685+ "notNull": true,
686+ "autoincrement": false
687+ },
688+ "default_workspace_id": {
689+ "name": "default_workspace_id",
690+ "type": "text",
691+ "primaryKey": false,
692+ "notNull": false,
693+ "autoincrement": false
694+ },
695+ "display_name": {
696+ "name": "display_name",
697+ "type": "text",
698+ "primaryKey": false,
699+ "notNull": true,
700+ "autoincrement": false
701+ },
702+ "runtime_mode": {
703+ "name": "runtime_mode",
704+ "type": "text",
705+ "primaryKey": false,
706+ "notNull": true,
707+ "autoincrement": false
708+ },
709+ "created_at": {
710+ "name": "created_at",
711+ "type": "integer",
712+ "primaryKey": false,
713+ "notNull": true,
714+ "autoincrement": false
715+ },
716+ "updated_at": {
717+ "name": "updated_at",
718+ "type": "integer",
719+ "primaryKey": false,
720+ "notNull": true,
721+ "autoincrement": false
722+ }
723+ },
724+ "indexes": {},
725+ "foreignKeys": {},
726+ "compositePrimaryKeys": {},
727+ "uniqueConstraints": {},
728+ "checkConstraints": {}
729+ },
730+ "source_auth_bindings": {
731+ "name": "source_auth_bindings",
732+ "columns": {
733+ "id": {
734+ "name": "id",
735+ "type": "text",
736+ "primaryKey": true,
737+ "notNull": true,
738+ "autoincrement": false
739+ },
740+ "source_id": {
741+ "name": "source_id",
742+ "type": "text",
743+ "primaryKey": false,
744+ "notNull": true,
745+ "autoincrement": false
746+ },
747+ "connection_id": {
748+ "name": "connection_id",
749+ "type": "text",
750+ "primaryKey": false,
751+ "notNull": true,
752+ "autoincrement": false
753+ },
754+ "organization_id": {
755+ "name": "organization_id",
756+ "type": "text",
757+ "primaryKey": false,
758+ "notNull": true,
759+ "autoincrement": false
760+ },
761+ "workspace_id": {
762+ "name": "workspace_id",
763+ "type": "text",
764+ "primaryKey": false,
765+ "notNull": false,
766+ "autoincrement": false
767+ },
768+ "account_id": {
769+ "name": "account_id",
770+ "type": "text",
771+ "primaryKey": false,
772+ "notNull": false,
773+ "autoincrement": false
774+ },
775+ "scope_type": {
776+ "name": "scope_type",
777+ "type": "text",
778+ "primaryKey": false,
779+ "notNull": true,
780+ "autoincrement": false
781+ },
782+ "selector": {
783+ "name": "selector",
784+ "type": "text",
785+ "primaryKey": false,
786+ "notNull": false,
787+ "autoincrement": false
788+ },
789+ "enabled": {
790+ "name": "enabled",
791+ "type": "integer",
792+ "primaryKey": false,
793+ "notNull": true,
794+ "autoincrement": false
795+ },
796+ "created_at": {
797+ "name": "created_at",
798+ "type": "integer",
799+ "primaryKey": false,
800+ "notNull": true,
801+ "autoincrement": false
802+ },
803+ "updated_at": {
804+ "name": "updated_at",
805+ "type": "integer",
806+ "primaryKey": false,
807+ "notNull": true,
808+ "autoincrement": false
809+ }
810+ },
811+ "indexes": {
812+ "source_auth_bindings_source_idx": {
813+ "name": "source_auth_bindings_source_idx",
814+ "columns": [
815+ "source_id"
816+ ],
817+ "isUnique": false
818+ },
819+ "source_auth_bindings_connection_idx": {
820+ "name": "source_auth_bindings_connection_idx",
821+ "columns": [
822+ "connection_id"
823+ ],
824+ "isUnique": false
825+ },
826+ "source_auth_bindings_org_idx": {
827+ "name": "source_auth_bindings_org_idx",
828+ "columns": [
829+ "organization_id"
830+ ],
831+ "isUnique": false
832+ },
833+ "source_auth_bindings_workspace_idx": {
834+ "name": "source_auth_bindings_workspace_idx",
835+ "columns": [
836+ "workspace_id"
837+ ],
838+ "isUnique": false
839+ },
840+ "source_auth_bindings_account_idx": {
841+ "name": "source_auth_bindings_account_idx",
842+ "columns": [
843+ "account_id"
844+ ],
845+ "isUnique": false
846+ }
847+ },
848+ "foreignKeys": {},
849+ "compositePrimaryKeys": {},
850+ "uniqueConstraints": {},
851+ "checkConstraints": {}
852+ },
853+ "sources": {
854+ "name": "sources",
855+ "columns": {
856+ "workspace_id": {
857+ "name": "workspace_id",
858+ "type": "text",
859+ "primaryKey": false,
860+ "notNull": true,
861+ "autoincrement": false
862+ },
863+ "source_id": {
864+ "name": "source_id",
865+ "type": "text",
866+ "primaryKey": false,
867+ "notNull": true,
868+ "autoincrement": false
869+ },
870+ "name": {
871+ "name": "name",
872+ "type": "text",
873+ "primaryKey": false,
874+ "notNull": true,
875+ "autoincrement": false
876+ },
877+ "kind": {
878+ "name": "kind",
879+ "type": "text",
880+ "primaryKey": false,
881+ "notNull": true,
882+ "autoincrement": false
883+ },
884+ "endpoint": {
885+ "name": "endpoint",
886+ "type": "text",
887+ "primaryKey": false,
888+ "notNull": true,
889+ "autoincrement": false
890+ },
891+ "status": {
892+ "name": "status",
893+ "type": "text",
894+ "primaryKey": false,
895+ "notNull": true,
896+ "autoincrement": false
897+ },
898+ "enabled": {
899+ "name": "enabled",
900+ "type": "integer",
901+ "primaryKey": false,
902+ "notNull": true,
903+ "autoincrement": false
904+ },
905+ "config_json": {
906+ "name": "config_json",
907+ "type": "text",
908+ "primaryKey": false,
909+ "notNull": true,
910+ "autoincrement": false
911+ },
912+ "source_hash": {
913+ "name": "source_hash",
914+ "type": "text",
915+ "primaryKey": false,
916+ "notNull": false,
917+ "autoincrement": false
918+ },
919+ "last_error": {
920+ "name": "last_error",
921+ "type": "text",
922+ "primaryKey": false,
923+ "notNull": false,
924+ "autoincrement": false
925+ },
926+ "created_at": {
927+ "name": "created_at",
928+ "type": "integer",
929+ "primaryKey": false,
930+ "notNull": true,
931+ "autoincrement": false
932+ },
933+ "updated_at": {
934+ "name": "updated_at",
935+ "type": "integer",
936+ "primaryKey": false,
937+ "notNull": true,
938+ "autoincrement": false
939+ }
940+ },
941+ "indexes": {
942+ "sources_workspace_name_idx": {
943+ "name": "sources_workspace_name_idx",
944+ "columns": [
945+ "workspace_id",
946+ "name"
947+ ],
948+ "isUnique": false
949+ }
950+ },
951+ "foreignKeys": {},
952+ "compositePrimaryKeys": {
953+ "sources_workspace_id_source_id_pk": {
954+ "columns": [
955+ "workspace_id",
956+ "source_id"
957+ ],
958+ "name": "sources_workspace_id_source_id_pk"
959+ }
960+ },
961+ "uniqueConstraints": {},
962+ "checkConstraints": {}
963+ },
964+ "storage_instances": {
965+ "name": "storage_instances",
966+ "columns": {
967+ "id": {
968+ "name": "id",
969+ "type": "text",
970+ "primaryKey": true,
971+ "notNull": true,
972+ "autoincrement": false
973+ },
974+ "scope_type": {
975+ "name": "scope_type",
976+ "type": "text",
977+ "primaryKey": false,
978+ "notNull": true,
979+ "autoincrement": false
980+ },
981+ "durability": {
982+ "name": "durability",
983+ "type": "text",
984+ "primaryKey": false,
985+ "notNull": true,
986+ "autoincrement": false
987+ },
988+ "status": {
989+ "name": "status",
990+ "type": "text",
991+ "primaryKey": false,
992+ "notNull": true,
993+ "autoincrement": false
994+ },
995+ "provider": {
996+ "name": "provider",
997+ "type": "text",
998+ "primaryKey": false,
999+ "notNull": true,
1000+ "autoincrement": false
1001+ },
1002+ "backend_key": {
1003+ "name": "backend_key",
1004+ "type": "text",
1005+ "primaryKey": false,
1006+ "notNull": true,
1007+ "autoincrement": false
1008+ },
1009+ "organization_id": {
1010+ "name": "organization_id",
1011+ "type": "text",
1012+ "primaryKey": false,
1013+ "notNull": true,
1014+ "autoincrement": false
1015+ },
1016+ "workspace_id": {
1017+ "name": "workspace_id",
1018+ "type": "text",
1019+ "primaryKey": false,
1020+ "notNull": false,
1021+ "autoincrement": false
1022+ },
1023+ "account_id": {
1024+ "name": "account_id",
1025+ "type": "text",
1026+ "primaryKey": false,
1027+ "notNull": false,
1028+ "autoincrement": false
1029+ },
1030+ "created_by_account_id": {
1031+ "name": "created_by_account_id",
1032+ "type": "text",
1033+ "primaryKey": false,
1034+ "notNull": false,
1035+ "autoincrement": false
1036+ },
1037+ "purpose": {
1038+ "name": "purpose",
1039+ "type": "text",
1040+ "primaryKey": false,
1041+ "notNull": false,
1042+ "autoincrement": false
1043+ },
1044+ "size_bytes": {
1045+ "name": "size_bytes",
1046+ "type": "integer",
1047+ "primaryKey": false,
1048+ "notNull": false,
1049+ "autoincrement": false
1050+ },
1051+ "file_count": {
1052+ "name": "file_count",
1053+ "type": "integer",
1054+ "primaryKey": false,
1055+ "notNull": false,
1056+ "autoincrement": false
1057+ },
1058+ "created_at": {
1059+ "name": "created_at",
1060+ "type": "integer",
1061+ "primaryKey": false,
1062+ "notNull": true,
1063+ "autoincrement": false
1064+ },
1065+ "updated_at": {
1066+ "name": "updated_at",
1067+ "type": "integer",
1068+ "primaryKey": false,
1069+ "notNull": true,
1070+ "autoincrement": false
1071+ },
1072+ "last_seen_at": {
1073+ "name": "last_seen_at",
1074+ "type": "integer",
1075+ "primaryKey": false,
1076+ "notNull": true,
1077+ "autoincrement": false
1078+ },
1079+ "closed_at": {
1080+ "name": "closed_at",
1081+ "type": "integer",
1082+ "primaryKey": false,
1083+ "notNull": false,
1084+ "autoincrement": false
1085+ },
1086+ "expires_at": {
1087+ "name": "expires_at",
1088+ "type": "integer",
1089+ "primaryKey": false,
1090+ "notNull": false,
1091+ "autoincrement": false
1092+ }
1093+ },
1094+ "indexes": {
1095+ "storage_instances_org_idx": {
1096+ "name": "storage_instances_org_idx",
1097+ "columns": [
1098+ "organization_id"
1099+ ],
1100+ "isUnique": false
1101+ },
1102+ "storage_instances_workspace_idx": {
1103+ "name": "storage_instances_workspace_idx",
1104+ "columns": [
1105+ "workspace_id"
1106+ ],
1107+ "isUnique": false
1108+ }
1109+ },
1110+ "foreignKeys": {},
1111+ "compositePrimaryKeys": {},
1112+ "uniqueConstraints": {},
1113+ "checkConstraints": {}
1114+ },
1115+ "sync_states": {
1116+ "name": "sync_states",
1117+ "columns": {
1118+ "id": {
1119+ "name": "id",
1120+ "type": "text",
1121+ "primaryKey": true,
1122+ "notNull": true,
1123+ "autoincrement": false
1124+ },
1125+ "workspace_id": {
1126+ "name": "workspace_id",
1127+ "type": "text",
1128+ "primaryKey": false,
1129+ "notNull": true,
1130+ "autoincrement": false
1131+ },
1132+ "target": {
1133+ "name": "target",
1134+ "type": "text",
1135+ "primaryKey": false,
1136+ "notNull": true,
1137+ "autoincrement": false
1138+ },
1139+ "target_url": {
1140+ "name": "target_url",
1141+ "type": "text",
1142+ "primaryKey": false,
1143+ "notNull": true,
1144+ "autoincrement": false
1145+ },
1146+ "linked_subject": {
1147+ "name": "linked_subject",
1148+ "type": "text",
1149+ "primaryKey": false,
1150+ "notNull": false,
1151+ "autoincrement": false
1152+ },
1153+ "cursor": {
1154+ "name": "cursor",
1155+ "type": "text",
1156+ "primaryKey": false,
1157+ "notNull": false,
1158+ "autoincrement": false
1159+ },
1160+ "last_sync_at": {
1161+ "name": "last_sync_at",
1162+ "type": "integer",
1163+ "primaryKey": false,
1164+ "notNull": false,
1165+ "autoincrement": false
1166+ },
1167+ "updated_at": {
1168+ "name": "updated_at",
1169+ "type": "integer",
1170+ "primaryKey": false,
1171+ "notNull": true,
1172+ "autoincrement": false
1173+ }
1174+ },
1175+ "indexes": {
1176+ "sync_states_workspace_idx": {
1177+ "name": "sync_states_workspace_idx",
1178+ "columns": [
1179+ "workspace_id"
1180+ ],
1181+ "isUnique": false
1182+ }
1183+ },
1184+ "foreignKeys": {},
1185+ "compositePrimaryKeys": {},
1186+ "uniqueConstraints": {},
1187+ "checkConstraints": {}
1188+ },
1189+ "task_runs": {
1190+ "name": "task_runs",
1191+ "columns": {
1192+ "id": {
1193+ "name": "id",
1194+ "type": "text",
1195+ "primaryKey": true,
1196+ "notNull": true,
1197+ "autoincrement": false
1198+ },
1199+ "workspace_id": {
1200+ "name": "workspace_id",
1201+ "type": "text",
1202+ "primaryKey": false,
1203+ "notNull": true,
1204+ "autoincrement": false
1205+ },
1206+ "account_id": {
1207+ "name": "account_id",
1208+ "type": "text",
1209+ "primaryKey": false,
1210+ "notNull": true,
1211+ "autoincrement": false
1212+ },
1213+ "session_id": {
1214+ "name": "session_id",
1215+ "type": "text",
1216+ "primaryKey": false,
1217+ "notNull": true,
1218+ "autoincrement": false
1219+ },
1220+ "runtime_id": {
1221+ "name": "runtime_id",
1222+ "type": "text",
1223+ "primaryKey": false,
1224+ "notNull": true,
1225+ "autoincrement": false
1226+ },
1227+ "code_hash": {
1228+ "name": "code_hash",
1229+ "type": "text",
1230+ "primaryKey": false,
1231+ "notNull": true,
1232+ "autoincrement": false
1233+ },
1234+ "status": {
1235+ "name": "status",
1236+ "type": "text",
1237+ "primaryKey": false,
1238+ "notNull": true,
1239+ "autoincrement": false
1240+ },
1241+ "started_at": {
1242+ "name": "started_at",
1243+ "type": "integer",
1244+ "primaryKey": false,
1245+ "notNull": false,
1246+ "autoincrement": false
1247+ },
1248+ "completed_at": {
1249+ "name": "completed_at",
1250+ "type": "integer",
1251+ "primaryKey": false,
1252+ "notNull": false,
1253+ "autoincrement": false
1254+ },
1255+ "exit_code": {
1256+ "name": "exit_code",
1257+ "type": "integer",
1258+ "primaryKey": false,
1259+ "notNull": false,
1260+ "autoincrement": false
1261+ },
1262+ "error": {
1263+ "name": "error",
1264+ "type": "text",
1265+ "primaryKey": false,
1266+ "notNull": false,
1267+ "autoincrement": false
1268+ }
1269+ },
1270+ "indexes": {
1271+ "task_runs_workspace_idx": {
1272+ "name": "task_runs_workspace_idx",
1273+ "columns": [
1274+ "workspace_id"
1275+ ],
1276+ "isUnique": false
1277+ }
1278+ },
1279+ "foreignKeys": {},
1280+ "compositePrimaryKeys": {},
1281+ "uniqueConstraints": {},
1282+ "checkConstraints": {}
1283+ },
1284+ "tool_artifacts": {
1285+ "name": "tool_artifacts",
1286+ "columns": {
1287+ "id": {
1288+ "name": "id",
1289+ "type": "text",
1290+ "primaryKey": false,
1291+ "notNull": true,
1292+ "autoincrement": false
1293+ },
1294+ "workspace_id": {
1295+ "name": "workspace_id",
1296+ "type": "text",
1297+ "primaryKey": false,
1298+ "notNull": true,
1299+ "autoincrement": false
1300+ },
1301+ "source_id": {
1302+ "name": "source_id",
1303+ "type": "text",
1304+ "primaryKey": false,
1305+ "notNull": true,
1306+ "autoincrement": false
1307+ },
1308+ "source_hash": {
1309+ "name": "source_hash",
1310+ "type": "text",
1311+ "primaryKey": false,
1312+ "notNull": true,
1313+ "autoincrement": false
1314+ },
1315+ "tool_count": {
1316+ "name": "tool_count",
1317+ "type": "integer",
1318+ "primaryKey": false,
1319+ "notNull": true,
1320+ "autoincrement": false
1321+ },
1322+ "manifest_json": {
1323+ "name": "manifest_json",
1324+ "type": "text",
1325+ "primaryKey": false,
1326+ "notNull": true,
1327+ "autoincrement": false
1328+ },
1329+ "created_at": {
1330+ "name": "created_at",
1331+ "type": "integer",
1332+ "primaryKey": false,
1333+ "notNull": true,
1334+ "autoincrement": false
1335+ },
1336+ "updated_at": {
1337+ "name": "updated_at",
1338+ "type": "integer",
1339+ "primaryKey": false,
1340+ "notNull": true,
1341+ "autoincrement": false
1342+ }
1343+ },
1344+ "indexes": {
1345+ "tool_artifacts_id_idx": {
1346+ "name": "tool_artifacts_id_idx",
1347+ "columns": [
1348+ "id"
1349+ ],
1350+ "isUnique": true
1351+ }
1352+ },
1353+ "foreignKeys": {},
1354+ "compositePrimaryKeys": {
1355+ "tool_artifacts_workspace_id_source_id_pk": {
1356+ "columns": [
1357+ "workspace_id",
1358+ "source_id"
1359+ ],
1360+ "name": "tool_artifacts_workspace_id_source_id_pk"
1361+ }
1362+ },
1363+ "uniqueConstraints": {},
1364+ "checkConstraints": {}
1365+ },
1366+ "workspaces": {
1367+ "name": "workspaces",
1368+ "columns": {
1369+ "id": {
1370+ "name": "id",
1371+ "type": "text",
1372+ "primaryKey": true,
1373+ "notNull": true,
1374+ "autoincrement": false
1375+ },
1376+ "organization_id": {
1377+ "name": "organization_id",
1378+ "type": "text",
1379+ "primaryKey": false,
1380+ "notNull": true,
1381+ "autoincrement": false
1382+ },
1383+ "name": {
1384+ "name": "name",
1385+ "type": "text",
1386+ "primaryKey": false,
1387+ "notNull": true,
1388+ "autoincrement": false
1389+ },
1390+ "created_by_account_id": {
1391+ "name": "created_by_account_id",
1392+ "type": "text",
1393+ "primaryKey": false,
1394+ "notNull": false,
1395+ "autoincrement": false
1396+ },
1397+ "created_at": {
1398+ "name": "created_at",
1399+ "type": "integer",
1400+ "primaryKey": false,
1401+ "notNull": true,
1402+ "autoincrement": false
1403+ },
1404+ "updated_at": {
1405+ "name": "updated_at",
1406+ "type": "integer",
1407+ "primaryKey": false,
1408+ "notNull": true,
1409+ "autoincrement": false
1410+ }
1411+ },
1412+ "indexes": {
1413+ "workspaces_org_idx": {
1414+ "name": "workspaces_org_idx",
1415+ "columns": [
1416+ "organization_id"
1417+ ],
1418+ "isUnique": false
1419+ }
1420+ },
1421+ "foreignKeys": {},
1422+ "compositePrimaryKeys": {},
1423+ "uniqueConstraints": {},
1424+ "checkConstraints": {}
1425+ }
1426+ },
1427+ "views": {},
1428+ "enums": {},
1429+ "_meta": {
1430+ "schemas": {},
1431+ "tables": {},
1432+ "columns": {}
1433+ },
1434+ "internal": {
1435+ "indexes": {}
1436+ }
1437+}
packages/persistence-sql/drizzle/sqlite/meta/_journal.json+13−0
@@ -0,0 +1,13 @@
1+{
2+ "version": "7",
3+ "dialect": "sqlite",
4+ "entries": [
5+ {
6+ "idx": 0,
7+ "version": "6",
8+ "when": 1772506139541,
9+ "tag": "0000_curved_raider",
10+ "breakpoints": true
11+ }
12+ ]
13+}
packages/persistence-sql/package.json+11−1
@@ -6,7 +6,14 @@ · 5 unmodified lines
66 ".": "./src/index.ts"
77 },
88 "scripts": {
9− "typecheck": "bunx tsc --noEmit -p tsconfig.json"
9+ "typecheck": "bunx tsc --noEmit -p tsconfig.json",
10+ "db:generate": "drizzle-kit generate --config drizzle.config.ts",
11+ "db:generate:pg": "drizzle-kit generate --config drizzle.config.pg.ts",
12+ "db:check": "drizzle-kit check --config drizzle.config.ts",
13+ "db:check:pg": "drizzle-kit check --config drizzle.config.pg.ts",
14+ "db:migrate": "drizzle-kit migrate --config drizzle.config.ts",
15+ "db:migrate:pg": "drizzle-kit migrate --config drizzle.config.pg.ts",
16+ "db:studio": "drizzle-kit studio --config drizzle.config.ts"
1017 },
1118 "dependencies": {
1219 "@executor-v2/persistence-ports": "workspace:*",
@@ -14,5 +21,8 @@ · 1 unmodified line
1421 "drizzle-orm": "^0.44.7",
1522 "effect": "catalog:",
1623 "postgres": "^3.4.7"
24+ },
25+ "devDependencies": {
26+ "drizzle-kit": "^0.31.9"
1727 }
1828 }
packages/persistence-sql/src/persistence-codecs.ts+0−52
@@ -1,52 +0,0 @@
1−import {
2− ApprovalSchema,
3− AuthConnectionSchema,
4− AuthMaterialSchema,
5− OAuthStateSchema,
6− OrganizationMembershipSchema,
7− OrganizationSchema,
8− PolicySchema,
9− ProfileSchema,
10− SourceAuthBindingSchema,
11− SourceSchema,
12− StorageInstanceSchema,
13− SyncStateSchema,
14− TaskRunSchema,
15− ToolArtifactSchema,
16− WorkspaceSchema,
17−} from "@executor-v2/schema";
18−import * as Schema from "effect/Schema";
19−
20−type JsonCodec<A> = {
21− encode: (value: A) => string;
22− decode: (value: string) => A;
23−};
24−
25−const makeJsonCodec = <A, I>(schema: Schema.Schema<A, I, never>): JsonCodec<A> => {
26− const jsonSchema = Schema.parseJson(schema);
27−
28− return {
29− encode: Schema.encodeSync(jsonSchema),
30− decode: Schema.decodeUnknownSync(jsonSchema),
31− };
32−};
33−
34−export const ProfileJson = makeJsonCodec(ProfileSchema);
35−export const OrganizationJson = makeJsonCodec(OrganizationSchema);
36−export const OrganizationMembershipJson = makeJsonCodec(
37− OrganizationMembershipSchema,
38−);
39−export const WorkspaceJson = makeJsonCodec(WorkspaceSchema);
40−export const SourceJson = makeJsonCodec(SourceSchema);
41−export const ToolArtifactJson = makeJsonCodec(ToolArtifactSchema);
42−export const AuthConnectionJson = makeJsonCodec(AuthConnectionSchema);
43−export const SourceAuthBindingJson = makeJsonCodec(
44− SourceAuthBindingSchema,
45−);
46−export const AuthMaterialJson = makeJsonCodec(AuthMaterialSchema);
47−export const OAuthStateJson = makeJsonCodec(OAuthStateSchema);
48−export const PolicyJson = makeJsonCodec(PolicySchema);
49−export const ApprovalJson = makeJsonCodec(ApprovalSchema);
50−export const TaskRunJson = makeJsonCodec(TaskRunSchema);
51−export const StorageInstanceJson = makeJsonCodec(StorageInstanceSchema);
52−export const SyncStateJson = makeJsonCodec(SyncStateSchema);
packages/persistence-sql/src/row-operations-auth.ts+199−92
@@ -7,12 +7,11 @@ import { · 6 unmodified lines
77 import { asc, eq } from "drizzle-orm";
88
99 import {
10− AuthConnectionJson,
11− AuthMaterialJson,
12− OAuthStateJson,
13− SourceAuthBindingJson,
14−} from "./persistence-codecs";
15−import { createDrizzleContext, type DrizzleDb, type DrizzleTables, type SqlAdapter } from "./sql-internals";
10+ createDrizzleContext,
11+ type DrizzleDb,
12+ type DrizzleTables,
13+ type SqlAdapter,
14+} from "./sql-internals";
1615
1716 type WriteLocked = <A>(run: () => Promise<A>) => Promise<A>;
1817
@@ -23,6 +22,79 @@ type AuthOperationsInput = { · 4 unmodified lines
2322 writeLocked: WriteLocked;
2423 };
2524
25+const toAuthConnection = (
26+ row: DrizzleTables["authConnectionsTable"]["$inferSelect"],
27+): AuthConnection => ({
28+ id: row.id as AuthConnection["id"],
29+ organizationId: row.organizationId as AuthConnection["organizationId"],
30+ workspaceId: row.workspaceId as AuthConnection["workspaceId"],
31+ accountId: row.accountId as AuthConnection["accountId"],
32+ ownerType: row.ownerType as AuthConnection["ownerType"],
33+ strategy: row.strategy as AuthConnection["strategy"],
34+ displayName: row.displayName,
35+ status: row.status as AuthConnection["status"],
36+ statusReason: row.statusReason,
37+ lastAuthErrorClass: row.lastAuthErrorClass,
38+ metadataJson: row.metadataJson,
39+ additionalHeadersJson: row.additionalHeadersJson,
40+ createdByAccountId: row.createdByAccountId as AuthConnection["createdByAccountId"],
41+ createdAt: row.createdAt,
42+ updatedAt: row.updatedAt,
43+ lastUsedAt: row.lastUsedAt,
44+});
45+
46+const toSourceAuthBinding = (
47+ row: DrizzleTables["sourceAuthBindingsTable"]["$inferSelect"],
48+): SourceAuthBinding => ({
49+ id: row.id as SourceAuthBinding["id"],
50+ sourceId: row.sourceId as SourceAuthBinding["sourceId"],
51+ connectionId: row.connectionId as SourceAuthBinding["connectionId"],
52+ organizationId: row.organizationId as SourceAuthBinding["organizationId"],
53+ workspaceId: row.workspaceId as SourceAuthBinding["workspaceId"],
54+ accountId: row.accountId as SourceAuthBinding["accountId"],
55+ scopeType: row.scopeType as SourceAuthBinding["scopeType"],
56+ selector: row.selector,
57+ enabled: row.enabled,
58+ createdAt: row.createdAt,
59+ updatedAt: row.updatedAt,
60+});
61+
62+const toAuthMaterial = (
63+ row: DrizzleTables["authMaterialsTable"]["$inferSelect"],
64+): AuthMaterial => ({
65+ id: row.id as AuthMaterial["id"],
66+ connectionId: row.connectionId as AuthMaterial["connectionId"],
67+ ciphertext: row.ciphertext,
68+ keyVersion: row.keyVersion,
69+ createdAt: row.createdAt,
70+ updatedAt: row.updatedAt,
71+});
72+
73+const toOAuthState = (
74+ row: DrizzleTables["oauthStatesTable"]["$inferSelect"],
75+): OAuthState => ({
76+ id: row.id as OAuthState["id"],
77+ connectionId: row.connectionId as OAuthState["connectionId"],
78+ accessTokenCiphertext: row.accessTokenCiphertext,
79+ refreshTokenCiphertext: row.refreshTokenCiphertext,
80+ keyVersion: row.keyVersion,
81+ expiresAt: row.expiresAt,
82+ scope: row.scope,
83+ tokenType: row.tokenType,
84+ issuer: row.issuer,
85+ refreshConfigJson: row.refreshConfigJson,
86+ tokenVersion: row.tokenVersion,
87+ leaseHolder: row.leaseHolder,
88+ leaseExpiresAt: row.leaseExpiresAt,
89+ leaseFence: row.leaseFence,
90+ lastRefreshAt: row.lastRefreshAt,
91+ lastRefreshErrorClass: row.lastRefreshErrorClass,
92+ lastRefreshError: row.lastRefreshError,
93+ reauthRequiredAt: row.reauthRequiredAt,
94+ createdAt: row.createdAt,
95+ updatedAt: row.updatedAt,
96+});
97+
2698 export const createAuthRowOperations = ({
2799 adapter,
28100 db,
@@ -30,35 +102,57 @@ export const createAuthRowOperations = ({ · 1 unmodified line
30102 writeLocked,
31103 }: AuthOperationsInput) => {
32104 const listAuthConnectionRows = async (): Promise<Array<AuthConnection>> => {
33− const rows = await db
34− .select({ payloadJson: tables.authConnectionsTable.payloadJson })
35− .from(tables.authConnectionsTable)
36− .orderBy(asc(tables.authConnectionsTable.updatedAt), asc(tables.authConnectionsTable.id));
105+ const rows = await db.select().from(tables.authConnectionsTable).orderBy(
106+ asc(tables.authConnectionsTable.updatedAt),
107+ asc(tables.authConnectionsTable.id),
108+ );
37109
38− return rows.map((row) => AuthConnectionJson.decode(row.payloadJson));
110+ return rows.map(toAuthConnection);
39111 };
40112
41113 const upsertAuthConnectionRow = async (connection: AuthConnection): Promise<void> => {
42114 await writeLocked(async () => {
43115 await adapter.transaction(async (transaction) => {
44116 const transactionContext = createDrizzleContext(transaction);
45− const payloadJson = AuthConnectionJson.encode(connection);
46− const now = Date.now();
47117
48118 await transactionContext.db
49119 .insert(transactionContext.tables.authConnectionsTable)
50120 .values({
51121 id: connection.id,
122+ organizationId: connection.organizationId,
52123 workspaceId: connection.workspaceId,
53− payloadJson,
54− updatedAt: now,
124+ accountId: connection.accountId,
125+ ownerType: connection.ownerType,
126+ strategy: connection.strategy,
127+ displayName: connection.displayName,
128+ status: connection.status,
129+ statusReason: connection.statusReason,
130+ lastAuthErrorClass: connection.lastAuthErrorClass,
131+ metadataJson: connection.metadataJson,
132+ additionalHeadersJson: connection.additionalHeadersJson,
133+ createdByAccountId: connection.createdByAccountId,
134+ createdAt: connection.createdAt,
135+ updatedAt: connection.updatedAt,
136+ lastUsedAt: connection.lastUsedAt,
55137 })
56138 .onConflictDoUpdate({
57139 target: transactionContext.tables.authConnectionsTable.id,
58140 set: {
141+ organizationId: connection.organizationId,
59142 workspaceId: connection.workspaceId,
60− payloadJson,
61− updatedAt: now,
143+ accountId: connection.accountId,
144+ ownerType: connection.ownerType,
145+ strategy: connection.strategy,
146+ displayName: connection.displayName,
147+ status: connection.status,
148+ statusReason: connection.statusReason,
149+ lastAuthErrorClass: connection.lastAuthErrorClass,
150+ metadataJson: connection.metadataJson,
151+ additionalHeadersJson: connection.additionalHeadersJson,
152+ createdByAccountId: connection.createdByAccountId,
153+ createdAt: connection.createdAt,
154+ updatedAt: connection.updatedAt,
155+ lastUsedAt: connection.lastUsedAt,
62156 },
63157 });
64158 });
@@ -90,15 +184,12 @@ export const createAuthRowOperations = ({ · 25 unmodified lines
90184 );
91185
92186 const listSourceAuthBindingRows = async (): Promise<Array<SourceAuthBinding>> => {
93− const rows = await db
94− .select({ payloadJson: tables.sourceAuthBindingsTable.payloadJson })
95− .from(tables.sourceAuthBindingsTable)
96− .orderBy(
97− asc(tables.sourceAuthBindingsTable.updatedAt),
98− asc(tables.sourceAuthBindingsTable.id),
99− );
100−
101− return rows.map((row) => SourceAuthBindingJson.decode(row.payloadJson));
187+ const rows = await db.select().from(tables.sourceAuthBindingsTable).orderBy(
188+ asc(tables.sourceAuthBindingsTable.updatedAt),
189+ asc(tables.sourceAuthBindingsTable.id),
190+ );
191+
192+ return rows.map(toSourceAuthBinding);
102193 };
103194
104195 const upsertSourceAuthBindingRow = async (
@@ -107,23 +198,35 @@ export const createAuthRowOperations = ({ · 2 unmodified lines
107198 await writeLocked(async () => {
108199 await adapter.transaction(async (transaction) => {
109200 const transactionContext = createDrizzleContext(transaction);
110− const payloadJson = SourceAuthBindingJson.encode(binding);
111− const now = Date.now();
112201
113202 await transactionContext.db
114203 .insert(transactionContext.tables.sourceAuthBindingsTable)
115204 .values({
116205 id: binding.id,
206+ sourceId: binding.sourceId,
207+ connectionId: binding.connectionId,
208+ organizationId: binding.organizationId,
117209 workspaceId: binding.workspaceId,
118− payloadJson,
119− updatedAt: now,
210+ accountId: binding.accountId,
211+ scopeType: binding.scopeType,
212+ selector: binding.selector,
213+ enabled: binding.enabled,
214+ createdAt: binding.createdAt,
215+ updatedAt: binding.updatedAt,
120216 })
121217 .onConflictDoUpdate({
122218 target: transactionContext.tables.sourceAuthBindingsTable.id,
123219 set: {
220+ sourceId: binding.sourceId,
221+ connectionId: binding.connectionId,
222+ organizationId: binding.organizationId,
124223 workspaceId: binding.workspaceId,
125− payloadJson,
126− updatedAt: now,
224+ accountId: binding.accountId,
225+ scopeType: binding.scopeType,
226+ selector: binding.selector,
227+ enabled: binding.enabled,
228+ createdAt: binding.createdAt,
229+ updatedAt: binding.updatedAt,
127230 },
128231 });
129232 });
@@ -155,35 +258,37 @@ export const createAuthRowOperations = ({ · 25 unmodified lines
155258 );
156259
157260 const listAuthMaterialRows = async (): Promise<Array<AuthMaterial>> => {
158− const rows = await db
159− .select({ payloadJson: tables.authMaterialsTable.payloadJson })
160− .from(tables.authMaterialsTable)
161− .orderBy(asc(tables.authMaterialsTable.updatedAt), asc(tables.authMaterialsTable.id));
261+ const rows = await db.select().from(tables.authMaterialsTable).orderBy(
262+ asc(tables.authMaterialsTable.updatedAt),
263+ asc(tables.authMaterialsTable.id),
264+ );
162265
163− return rows.map((row) => AuthMaterialJson.decode(row.payloadJson));
266+ return rows.map(toAuthMaterial);
164267 };
165268
166269 const upsertAuthMaterialRow = async (material: AuthMaterial): Promise<void> => {
167270 await writeLocked(async () => {
168271 await adapter.transaction(async (transaction) => {
169272 const transactionContext = createDrizzleContext(transaction);
170− const payloadJson = AuthMaterialJson.encode(material);
171− const now = Date.now();
172273
173274 await transactionContext.db
174275 .insert(transactionContext.tables.authMaterialsTable)
175276 .values({
176277 id: material.id,
177− workspaceId: null,
178− payloadJson,
179− updatedAt: now,
278+ connectionId: material.connectionId,
279+ ciphertext: material.ciphertext,
280+ keyVersion: material.keyVersion,
281+ createdAt: material.createdAt,
282+ updatedAt: material.updatedAt,
180283 })
181284 .onConflictDoUpdate({
182285 target: transactionContext.tables.authMaterialsTable.id,
183286 set: {
184− workspaceId: null,
185− payloadJson,
186− updatedAt: now,
287+ connectionId: material.connectionId,
288+ ciphertext: material.ciphertext,
289+ keyVersion: material.keyVersion,
290+ createdAt: material.createdAt,
291+ updatedAt: material.updatedAt,
187292 },
188293 });
189294 });
@@ -196,57 +301,73 @@ export const createAuthRowOperations = ({ · 6 unmodified lines
196301 await writeLocked(async () => {
197302 await adapter.transaction(async (transaction) => {
198303 const transactionContext = createDrizzleContext(transaction);
199− const existing = await transactionContext.db
200− .select({
201− id: transactionContext.tables.authMaterialsTable.id,
202− payloadJson: transactionContext.tables.authMaterialsTable.payloadJson,
203− })
204− .from(transactionContext.tables.authMaterialsTable);
205−
206− for (const row of existing) {
207− const material = AuthMaterialJson.decode(row.payloadJson);
208− if (material.connectionId !== connectionId) {
209− continue;
210− }
211−
212− await transactionContext.db
213− .delete(transactionContext.tables.authMaterialsTable)
214− .where(eq(transactionContext.tables.authMaterialsTable.id, row.id));
215− }
304+ await transactionContext.db
305+ .delete(transactionContext.tables.authMaterialsTable)
306+ .where(eq(transactionContext.tables.authMaterialsTable.connectionId, connectionId));
216307 });
217308 });
218309 };
219310
220311 const listOAuthStateRows = async (): Promise<Array<OAuthState>> => {
221− const rows = await db
222− .select({ payloadJson: tables.oauthStatesTable.payloadJson })
223− .from(tables.oauthStatesTable)
224− .orderBy(asc(tables.oauthStatesTable.updatedAt), asc(tables.oauthStatesTable.id));
312+ const rows = await db.select().from(tables.oauthStatesTable).orderBy(
313+ asc(tables.oauthStatesTable.updatedAt),
314+ asc(tables.oauthStatesTable.id),
315+ );
225316
226− return rows.map((row) => OAuthStateJson.decode(row.payloadJson));
317+ return rows.map(toOAuthState);
227318 };
228319
229320 const upsertOAuthStateRow = async (state: OAuthState): Promise<void> => {
230321 await writeLocked(async () => {
231322 await adapter.transaction(async (transaction) => {
232323 const transactionContext = createDrizzleContext(transaction);
233− const payloadJson = OAuthStateJson.encode(state);
234− const now = Date.now();
235324
236325 await transactionContext.db
237326 .insert(transactionContext.tables.oauthStatesTable)
238327 .values({
239328 id: state.id,
240− workspaceId: null,
241− payloadJson,
242− updatedAt: now,
329+ connectionId: state.connectionId,
330+ accessTokenCiphertext: state.accessTokenCiphertext,
331+ refreshTokenCiphertext: state.refreshTokenCiphertext,
332+ keyVersion: state.keyVersion,
333+ expiresAt: state.expiresAt,
334+ scope: state.scope,
335+ tokenType: state.tokenType,
336+ issuer: state.issuer,
337+ refreshConfigJson: state.refreshConfigJson,
338+ tokenVersion: state.tokenVersion,
339+ leaseHolder: state.leaseHolder,
340+ leaseExpiresAt: state.leaseExpiresAt,
341+ leaseFence: state.leaseFence,
342+ lastRefreshAt: state.lastRefreshAt,
343+ lastRefreshErrorClass: state.lastRefreshErrorClass,
344+ lastRefreshError: state.lastRefreshError,
345+ reauthRequiredAt: state.reauthRequiredAt,
346+ createdAt: state.createdAt,
347+ updatedAt: state.updatedAt,
243348 })
244349 .onConflictDoUpdate({
245350 target: transactionContext.tables.oauthStatesTable.id,
246351 set: {
247− workspaceId: null,
248− payloadJson,
249− updatedAt: now,
352+ connectionId: state.connectionId,
353+ accessTokenCiphertext: state.accessTokenCiphertext,
354+ refreshTokenCiphertext: state.refreshTokenCiphertext,
355+ keyVersion: state.keyVersion,
356+ expiresAt: state.expiresAt,
357+ scope: state.scope,
358+ tokenType: state.tokenType,
359+ issuer: state.issuer,
360+ refreshConfigJson: state.refreshConfigJson,
361+ tokenVersion: state.tokenVersion,
362+ leaseHolder: state.leaseHolder,
363+ leaseExpiresAt: state.leaseExpiresAt,
364+ leaseFence: state.leaseFence,
365+ lastRefreshAt: state.lastRefreshAt,
366+ lastRefreshErrorClass: state.lastRefreshErrorClass,
367+ lastRefreshError: state.lastRefreshError,
368+ reauthRequiredAt: state.reauthRequiredAt,
369+ createdAt: state.createdAt,
370+ updatedAt: state.updatedAt,
250371 },
251372 });
252373 });
@@ -259,23 +380,9 @@ export const createAuthRowOperations = ({ · 6 unmodified lines
259380 await writeLocked(async () => {
260381 await adapter.transaction(async (transaction) => {
261382 const transactionContext = createDrizzleContext(transaction);
262− const existing = await transactionContext.db
263− .select({
264− id: transactionContext.tables.oauthStatesTable.id,
265− payloadJson: transactionContext.tables.oauthStatesTable.payloadJson,
266− })
267− .from(transactionContext.tables.oauthStatesTable);
268−
269− for (const row of existing) {
270− const state = OAuthStateJson.decode(row.payloadJson);
271− if (state.connectionId !== connectionId) {
272− continue;
273− }
274−
275− await transactionContext.db
276− .delete(transactionContext.tables.oauthStatesTable)
277− .where(eq(transactionContext.tables.oauthStatesTable.id, row.id));
278− }
383+ await transactionContext.db
384+ .delete(transactionContext.tables.oauthStatesTable)
385+ .where(eq(transactionContext.tables.oauthStatesTable.connectionId, connectionId));
279386 });
280387 });
281388 };
packages/persistence-sql/src/row-operations-core.ts+252−125
@@ -7,18 +7,14 @@ import { · 6 unmodified lines
77 type StorageInstance,
88 type Workspace,
99 } from "@executor-v2/schema";
10−import { asc, eq } from "drizzle-orm";
10+import { asc, desc, eq } from "drizzle-orm";
1111
1212 import {
13− ApprovalJson,
14− OrganizationJson,
15− OrganizationMembershipJson,
16− PolicyJson,
17− ProfileJson,
18− StorageInstanceJson,
19− WorkspaceJson,
20−} from "./persistence-codecs";
21−import { createDrizzleContext, type DrizzleDb, type DrizzleTables, type SqlAdapter } from "./sql-internals";
13+ createDrizzleContext,
14+ type DrizzleDb,
15+ type DrizzleTables,
16+ type SqlAdapter,
17+} from "./sql-internals";
2218
2319 type WriteLocked = <A>(run: () => Promise<A>) => Promise<A>;
2420
@@ -29,6 +25,103 @@ type CoreOperationsInput = { · 4 unmodified lines
2925 writeLocked: WriteLocked;
3026 };
3127
28+const toOrganization = (
29+ row: DrizzleTables["organizationsTable"]["$inferSelect"],
30+): Organization => ({
31+ id: row.id as Organization["id"],
32+ slug: row.slug,
33+ name: row.name,
34+ status: row.status as Organization["status"],
35+ createdByAccountId: row.createdByAccountId as Organization["createdByAccountId"],
36+ createdAt: row.createdAt,
37+ updatedAt: row.updatedAt,
38+});
39+
40+const toOrganizationMembership = (
41+ row: DrizzleTables["organizationMembershipsTable"]["$inferSelect"],
42+): OrganizationMembership => ({
43+ id: row.id as OrganizationMembership["id"],
44+ organizationId: row.organizationId as OrganizationMembership["organizationId"],
45+ accountId: row.accountId as OrganizationMembership["accountId"],
46+ role: row.role as OrganizationMembership["role"],
47+ status: row.status as OrganizationMembership["status"],
48+ billable: row.billable,
49+ invitedByAccountId:
50+ row.invitedByAccountId as OrganizationMembership["invitedByAccountId"],
51+ joinedAt: row.joinedAt,
52+ createdAt: row.createdAt,
53+ updatedAt: row.updatedAt,
54+});
55+
56+const toWorkspace = (
57+ row: DrizzleTables["workspacesTable"]["$inferSelect"],
58+): Workspace => ({
59+ id: row.id as Workspace["id"],
60+ organizationId: row.organizationId as Workspace["organizationId"],
61+ name: row.name,
62+ createdByAccountId: row.createdByAccountId as Workspace["createdByAccountId"],
63+ createdAt: row.createdAt,
64+ updatedAt: row.updatedAt,
65+});
66+
67+const toStorageInstance = (
68+ row: DrizzleTables["storageInstancesTable"]["$inferSelect"],
69+): StorageInstance => ({
70+ id: row.id as StorageInstance["id"],
71+ scopeType: row.scopeType as StorageInstance["scopeType"],
72+ durability: row.durability as StorageInstance["durability"],
73+ status: row.status as StorageInstance["status"],
74+ provider: row.provider as StorageInstance["provider"],
75+ backendKey: row.backendKey,
76+ organizationId: row.organizationId as StorageInstance["organizationId"],
77+ workspaceId: row.workspaceId as StorageInstance["workspaceId"],
78+ accountId: row.accountId as StorageInstance["accountId"],
79+ createdByAccountId: row.createdByAccountId as StorageInstance["createdByAccountId"],
80+ purpose: row.purpose,
81+ sizeBytes: row.sizeBytes,
82+ fileCount: row.fileCount,
83+ createdAt: row.createdAt,
84+ updatedAt: row.updatedAt,
85+ lastSeenAt: row.lastSeenAt,
86+ closedAt: row.closedAt,
87+ expiresAt: row.expiresAt,
88+});
89+
90+const toPolicy = (
91+ row: DrizzleTables["policiesTable"]["$inferSelect"],
92+): Policy => ({
93+ id: row.id as Policy["id"],
94+ workspaceId: row.workspaceId as Policy["workspaceId"],
95+ toolPathPattern: row.toolPathPattern,
96+ decision: row.decision as Policy["decision"],
97+ createdAt: row.createdAt,
98+ updatedAt: row.updatedAt,
99+});
100+
101+const toApproval = (
102+ row: DrizzleTables["approvalsTable"]["$inferSelect"],
103+): Approval => ({
104+ id: row.id as Approval["id"],
105+ workspaceId: row.workspaceId as Approval["workspaceId"],
106+ taskRunId: row.taskRunId as Approval["taskRunId"],
107+ callId: row.callId,
108+ toolPath: row.toolPath,
109+ status: row.status as Approval["status"],
110+ inputPreviewJson: row.inputPreviewJson,
111+ reason: row.reason,
112+ requestedAt: row.requestedAt,
113+ resolvedAt: row.resolvedAt,
114+});
115+
116+const toProfile = (row: DrizzleTables["profileTable"]["$inferSelect"]): Profile => ({
117+ id: row.id as Profile["id"],
118+ defaultWorkspaceId: row.defaultWorkspaceId as Profile["defaultWorkspaceId"],
119+ displayName: row.displayName,
120+ runtimeMode: row.runtimeMode as Profile["runtimeMode"],
121+ createdAt: row.createdAt,
122+ updatedAt: row.updatedAt,
123+});
124+
32125 export const createCoreRowOperations = ({
33126 adapter,
34127 db,
@@ -36,38 +129,39 @@ export const createCoreRowOperations = ({ · 1 unmodified line
36129 writeLocked,
37130 }: CoreOperationsInput) => {
38131 const listOrganizationsRows = async (): Promise<Array<Organization>> => {
39− const rows = await db
40− .select({ payloadJson: tables.organizationsTable.payloadJson })
41− .from(tables.organizationsTable)
42− .orderBy(
43− asc(tables.organizationsTable.updatedAt),
44− asc(tables.organizationsTable.id),
45− );
46−
47− return rows.map((row) => OrganizationJson.decode(row.payloadJson));
132+ const rows = await db.select().from(tables.organizationsTable).orderBy(
133+ asc(tables.organizationsTable.updatedAt),
134+ asc(tables.organizationsTable.id),
135+ );
136+
137+ return rows.map(toOrganization);
48138 };
49139
50− const upsertOrganizationRow = async (
51− organization: Organization,
52− ): Promise<void> => {
140+ const upsertOrganizationRow = async (organization: Organization): Promise<void> => {
53141 await writeLocked(async () => {
54142 await adapter.transaction(async (transaction) => {
55143 const transactionContext = createDrizzleContext(transaction);
56− const payloadJson = OrganizationJson.encode(organization);
57− const now = Date.now();
58144
59145 await transactionContext.db
60146 .insert(transactionContext.tables.organizationsTable)
61147 .values({
62148 id: organization.id,
63− payloadJson,
64− updatedAt: now,
149+ slug: organization.slug,
150+ name: organization.name,
151+ status: organization.status,
152+ createdByAccountId: organization.createdByAccountId,
153+ createdAt: organization.createdAt,
154+ updatedAt: organization.updatedAt,
65155 })
66156 .onConflictDoUpdate({
67157 target: transactionContext.tables.organizationsTable.id,
68158 set: {
69− payloadJson,
70− updatedAt: now,
159+ slug: organization.slug,
160+ name: organization.name,
161+ status: organization.status,
162+ createdByAccountId: organization.createdByAccountId,
163+ createdAt: organization.createdAt,
164+ updatedAt: organization.updatedAt,
71165 },
72166 });
73167 });
@@ -77,15 +171,12 @@ export const createCoreRowOperations = ({ · 3 unmodified lines
77171 const listOrganizationMembershipRows = async (): Promise<
78172 Array<OrganizationMembership>
79173 > => {
80− const rows = await db
81− .select({ payloadJson: tables.organizationMembershipsTable.payloadJson })
82− .from(tables.organizationMembershipsTable)
83− .orderBy(
84− asc(tables.organizationMembershipsTable.updatedAt),
85− asc(tables.organizationMembershipsTable.id),
86− );
87−
88− return rows.map((row) => OrganizationMembershipJson.decode(row.payloadJson));
174+ const rows = await db.select().from(tables.organizationMembershipsTable).orderBy(
175+ asc(tables.organizationMembershipsTable.updatedAt),
176+ asc(tables.organizationMembershipsTable.id),
177+ );
178+
179+ return rows.map(toOrganizationMembership);
89180 };
90181
91182 const upsertOrganizationMembershipRow = async (
@@ -94,23 +185,33 @@ export const createCoreRowOperations = ({ · 2 unmodified lines
94185 await writeLocked(async () => {
95186 await adapter.transaction(async (transaction) => {
96187 const transactionContext = createDrizzleContext(transaction);
97− const payloadJson = OrganizationMembershipJson.encode(membership);
98− const now = Date.now();
99188
100189 await transactionContext.db
101190 .insert(transactionContext.tables.organizationMembershipsTable)
102191 .values({
103192 id: membership.id,
104− workspaceId: null,
105− payloadJson,
106− updatedAt: now,
193+ organizationId: membership.organizationId,
194+ accountId: membership.accountId,
195+ role: membership.role,
196+ status: membership.status,
197+ billable: membership.billable,
198+ invitedByAccountId: membership.invitedByAccountId,
199+ joinedAt: membership.joinedAt,
200+ createdAt: membership.createdAt,
201+ updatedAt: membership.updatedAt,
107202 })
108203 .onConflictDoUpdate({
109204 target: transactionContext.tables.organizationMembershipsTable.id,
110205 set: {
111− workspaceId: null,
112− payloadJson,
113− updatedAt: now,
206+ organizationId: membership.organizationId,
207+ accountId: membership.accountId,
208+ role: membership.role,
209+ status: membership.status,
210+ billable: membership.billable,
211+ invitedByAccountId: membership.invitedByAccountId,
212+ joinedAt: membership.joinedAt,
213+ createdAt: membership.createdAt,
214+ updatedAt: membership.updatedAt,
114215 },
115216 });
116217 });
@@ -118,38 +219,37 @@ export const createCoreRowOperations = ({ · 1 unmodified line
118219 };
119220
120221 const listWorkspaceRows = async (): Promise<Array<Workspace>> => {
121− const rows = await db
122− .select({ payloadJson: tables.workspacesTable.payloadJson })
123− .from(tables.workspacesTable)
124− .orderBy(
125− asc(tables.workspacesTable.updatedAt),
126− asc(tables.workspacesTable.id),
127− );
128−
129− return rows.map((row) => WorkspaceJson.decode(row.payloadJson));
222+ const rows = await db.select().from(tables.workspacesTable).orderBy(
223+ asc(tables.workspacesTable.updatedAt),
224+ asc(tables.workspacesTable.id),
225+ );
226+
227+ return rows.map(toWorkspace);
130228 };
131229
132230 const upsertWorkspaceRow = async (workspace: Workspace): Promise<void> => {
133231 await writeLocked(async () => {
134232 await adapter.transaction(async (transaction) => {
135233 const transactionContext = createDrizzleContext(transaction);
136− const payloadJson = WorkspaceJson.encode(workspace);
137− const now = Date.now();
138234
139235 await transactionContext.db
140236 .insert(transactionContext.tables.workspacesTable)
141237 .values({
142238 id: workspace.id,
143− workspaceId: workspace.organizationId,
144− payloadJson,
145− updatedAt: now,
239+ organizationId: workspace.organizationId,
240+ name: workspace.name,
241+ createdByAccountId: workspace.createdByAccountId,
242+ createdAt: workspace.createdAt,
243+ updatedAt: workspace.updatedAt,
146244 })
147245 .onConflictDoUpdate({
148246 target: transactionContext.tables.workspacesTable.id,
149247 set: {
150− workspaceId: workspace.organizationId,
151− payloadJson,
152− updatedAt: now,
248+ organizationId: workspace.organizationId,
249+ name: workspace.name,
250+ createdByAccountId: workspace.createdByAccountId,
251+ createdAt: workspace.createdAt,
252+ updatedAt: workspace.updatedAt,
153253 },
154254 });
155255 });
@@ -157,15 +257,12 @@ export const createCoreRowOperations = ({ · 1 unmodified line
157257 };
158258
159259 const listStorageInstanceRows = async (): Promise<Array<StorageInstance>> => {
160− const rows = await db
161− .select({ payloadJson: tables.storageInstancesTable.payloadJson })
162− .from(tables.storageInstancesTable)
163− .orderBy(
164− asc(tables.storageInstancesTable.updatedAt),
165− asc(tables.storageInstancesTable.id),
166− );
167−
168− return rows.map((row) => StorageInstanceJson.decode(row.payloadJson));
260+ const rows = await db.select().from(tables.storageInstancesTable).orderBy(
261+ asc(tables.storageInstancesTable.updatedAt),
262+ asc(tables.storageInstancesTable.id),
263+ );
264+
265+ return rows.map(toStorageInstance);
169266 };
170267
171268 const upsertStorageInstanceRow = async (
@@ -174,23 +271,49 @@ export const createCoreRowOperations = ({ · 2 unmodified lines
174271 await writeLocked(async () => {
175272 await adapter.transaction(async (transaction) => {
176273 const transactionContext = createDrizzleContext(transaction);
177− const payloadJson = StorageInstanceJson.encode(storageInstance);
178− const now = Date.now();
179274
180275 await transactionContext.db
181276 .insert(transactionContext.tables.storageInstancesTable)
182277 .values({
183278 id: storageInstance.id,
279+ scopeType: storageInstance.scopeType,
280+ durability: storageInstance.durability,
281+ status: storageInstance.status,
282+ provider: storageInstance.provider,
283+ backendKey: storageInstance.backendKey,
284+ organizationId: storageInstance.organizationId,
184285 workspaceId: storageInstance.workspaceId,
185− payloadJson,
186− updatedAt: now,
286+ accountId: storageInstance.accountId,
287+ createdByAccountId: storageInstance.createdByAccountId,
288+ purpose: storageInstance.purpose,
289+ sizeBytes: storageInstance.sizeBytes,
290+ fileCount: storageInstance.fileCount,
291+ createdAt: storageInstance.createdAt,
292+ updatedAt: storageInstance.updatedAt,
293+ lastSeenAt: storageInstance.lastSeenAt,
294+ closedAt: storageInstance.closedAt,
295+ expiresAt: storageInstance.expiresAt,
187296 })
188297 .onConflictDoUpdate({
189298 target: transactionContext.tables.storageInstancesTable.id,
190299 set: {
300+ scopeType: storageInstance.scopeType,
301+ durability: storageInstance.durability,
302+ status: storageInstance.status,
303+ provider: storageInstance.provider,
304+ backendKey: storageInstance.backendKey,
305+ organizationId: storageInstance.organizationId,
191306 workspaceId: storageInstance.workspaceId,
192− payloadJson,
193− updatedAt: now,
307+ accountId: storageInstance.accountId,
308+ createdByAccountId: storageInstance.createdByAccountId,
309+ purpose: storageInstance.purpose,
310+ sizeBytes: storageInstance.sizeBytes,
311+ fileCount: storageInstance.fileCount,
312+ createdAt: storageInstance.createdAt,
313+ updatedAt: storageInstance.updatedAt,
314+ lastSeenAt: storageInstance.lastSeenAt,
315+ closedAt: storageInstance.closedAt,
316+ expiresAt: storageInstance.expiresAt,
194317 },
195318 });
196319 });
@@ -222,43 +345,45 @@ export const createCoreRowOperations = ({ · 25 unmodified lines
222345 );
223346
224347 const listPolicyRows = async (): Promise<Array<Policy>> => {
225− const rows = await db
226− .select({ payloadJson: tables.policiesTable.payloadJson })
227− .from(tables.policiesTable)
228− .orderBy(asc(tables.policiesTable.updatedAt), asc(tables.policiesTable.id));
348+ const rows = await db.select().from(tables.policiesTable).orderBy(
349+ asc(tables.policiesTable.updatedAt),
350+ asc(tables.policiesTable.id),
351+ );
229352
230− return rows.map((row) => PolicyJson.decode(row.payloadJson));
353+ return rows.map(toPolicy);
231354 };
232355
233356 const upsertPolicyRow = async (policy: Policy): Promise<void> => {
234357 await writeLocked(async () => {
235358 await adapter.transaction(async (transaction) => {
236359 const transactionContext = createDrizzleContext(transaction);
237− const payloadJson = PolicyJson.encode(policy);
238− const now = Date.now();
239360
240361 await transactionContext.db
241362 .insert(transactionContext.tables.policiesTable)
242363 .values({
243364 id: policy.id,
244365 workspaceId: policy.workspaceId,
245− payloadJson,
246− updatedAt: now,
366+ toolPathPattern: policy.toolPathPattern,
367+ decision: policy.decision,
368+ createdAt: policy.createdAt,
369+ updatedAt: policy.updatedAt,
247370 })
248371 .onConflictDoUpdate({
249372 target: transactionContext.tables.policiesTable.id,
250373 set: {
251374 workspaceId: policy.workspaceId,
252− payloadJson,
253− updatedAt: now,
375+ toolPathPattern: policy.toolPathPattern,
376+ decision: policy.decision,
377+ createdAt: policy.createdAt,
378+ updatedAt: policy.updatedAt,
254379 },
255380 });
256381 });
257382 });
258383 };
259384
260− const removePolicyRowById = async (policyId: Policy["id"]): Promise<boolean> => {
261− return writeLocked(async () =>
385+ const removePolicyRowById = async (policyId: Policy["id"]): Promise<boolean> =>
386+ writeLocked(async () =>
262387 adapter.transaction(async (transaction) => {
263388 const transactionContext = createDrizzleContext(transaction);
264389
@@ -279,38 +404,47 @@ export const createCoreRowOperations = ({ · 14 unmodified lines
279404 return true;
280405 })
281406 );
282− };
283407
284408 const listApprovalRows = async (): Promise<Array<Approval>> => {
285− const rows = await db
286− .select({ payloadJson: tables.approvalsTable.payloadJson })
287− .from(tables.approvalsTable)
288− .orderBy(asc(tables.approvalsTable.updatedAt), asc(tables.approvalsTable.id));
409+ const rows = await db.select().from(tables.approvalsTable).orderBy(
410+ asc(tables.approvalsTable.requestedAt),
411+ asc(tables.approvalsTable.id),
412+ );
289413
290− return rows.map((row) => ApprovalJson.decode(row.payloadJson));
414+ return rows.map(toApproval);
291415 };
292416
293417 const upsertApprovalRow = async (approval: Approval): Promise<void> => {
294418 await writeLocked(async () => {
295419 await adapter.transaction(async (transaction) => {
296420 const transactionContext = createDrizzleContext(transaction);
297− const payloadJson = ApprovalJson.encode(approval);
298− const now = Date.now();
299421
300422 await transactionContext.db
301423 .insert(transactionContext.tables.approvalsTable)
302424 .values({
303425 id: approval.id,
304426 workspaceId: approval.workspaceId,
305− payloadJson,
306− updatedAt: now,
427+ taskRunId: approval.taskRunId,
428+ callId: approval.callId,
429+ toolPath: approval.toolPath,
430+ status: approval.status,
431+ inputPreviewJson: approval.inputPreviewJson,
432+ reason: approval.reason,
433+ requestedAt: approval.requestedAt,
434+ resolvedAt: approval.resolvedAt,
307435 })
308436 .onConflictDoUpdate({
309437 target: transactionContext.tables.approvalsTable.id,
310438 set: {
311439 workspaceId: approval.workspaceId,
312− payloadJson,
313− updatedAt: now,
440+ taskRunId: approval.taskRunId,
441+ callId: approval.callId,
442+ toolPath: approval.toolPath,
443+ status: approval.status,
444+ inputPreviewJson: approval.inputPreviewJson,
445+ reason: approval.reason,
446+ requestedAt: approval.requestedAt,
447+ resolvedAt: approval.resolvedAt,
314448 },
315449 });
316450 });
@@ -318,49 +452,42 @@ export const createCoreRowOperations = ({ · 1 unmodified line
318452 };
319453
320454 const getProfileRow = async (): Promise<Profile | null> => {
321− const rows = await db
322− .select({ profileJson: tables.profileTable.profileJson })
323− .from(tables.profileTable)
324− .where(eq(tables.profileTable.id, 1))
325− .limit(1);
455+ const rows = await db.select().from(tables.profileTable).orderBy(
456+ desc(tables.profileTable.updatedAt),
457+ asc(tables.profileTable.id),
458+ ).limit(1);
326459
327460 const row = rows[0];
328461 if (!row) {
329462 return null;
330463 }
331464
332− return ProfileJson.decode(row.profileJson);
465+ return toProfile(row);
333466 };
334467
335468 const upsertProfileRow = async (profile: Profile): Promise<void> => {
336469 await writeLocked(async () => {
337470 await adapter.transaction(async (transaction) => {
338471 const transactionContext = createDrizzleContext(transaction);
339− const currentRows = await transactionContext.db
340− .select({ schemaVersion: transactionContext.tables.profileTable.schemaVersion })
341− .from(transactionContext.tables.profileTable)
342− .where(eq(transactionContext.tables.profileTable.id, 1))
343− .limit(1);
344−
345− const schemaVersion = currentRows[0]?.schemaVersion ?? 1;
346− const now = Date.now();
347− const profileJson = ProfileJson.encode(profile);
348472
349473 await transactionContext.db
350474 .insert(transactionContext.tables.profileTable)
351475 .values({
352− id: 1,
353− schemaVersion,
354− generatedAt: now,
355− profileJson,
356− updatedAt: now,
476+ id: profile.id,
477+ defaultWorkspaceId: profile.defaultWorkspaceId,
478+ displayName: profile.displayName,
479+ runtimeMode: profile.runtimeMode,
480+ createdAt: profile.createdAt,
481+ updatedAt: profile.updatedAt,
357482 })
358483 .onConflictDoUpdate({
359484 target: transactionContext.tables.profileTable.id,
360485 set: {
361− profileJson,
362− generatedAt: now,
363− updatedAt: now,
486+ defaultWorkspaceId: profile.defaultWorkspaceId,
487+ displayName: profile.displayName,
488+ runtimeMode: profile.runtimeMode,
489+ createdAt: profile.createdAt,
490+ updatedAt: profile.updatedAt,
364491 },
365492 });
366493 });
packages/persistence-sql/src/rows-effect-api-auth.ts+116−0
@@ -0,0 +1,116 @@
1+import {
2+ type AuthConnection,
3+ type AuthMaterial,
4+ type OAuthState,
5+ type SourceAuthBinding,
6+} from "@executor-v2/schema";
7+
8+import { tableNames } from "./schema";
9+import { type SqlBackend } from "./sql-internals";
10+import {
11+ type RowOperations,
12+ toBooleanEffect,
13+ toListEffect,
14+ toVoidEffect,
15+} from "./rows-effect-helpers";
16+
17+export const createAuthRowsEffectApi = (
18+ backend: SqlBackend,
19+ operations: RowOperations,
20+) => ({
21+ authConnections: {
22+ list: () =>
23+ toListEffect<AuthConnection>(
24+ backend,
25+ "rows.authConnections.list",
26+ tableNames.authConnections,
27+ operations.listAuthConnectionRows,
28+ ),
29+ upsert: (connection: AuthConnection) =>
30+ toVoidEffect(
31+ backend,
32+ "rows.authConnections.upsert",
33+ tableNames.authConnections,
34+ () => operations.upsertAuthConnectionRow(connection),
35+ ),
36+ removeById: (connectionId: AuthConnection["id"]) =>
37+ toBooleanEffect(
38+ backend,
39+ "rows.authConnections.remove",
40+ tableNames.authConnections,
41+ () => operations.removeAuthConnectionRowById(connectionId),
42+ ),
43+ },
44+
45+ sourceAuthBindings: {
46+ list: () =>
47+ toListEffect<SourceAuthBinding>(
48+ backend,
49+ "rows.sourceAuthBindings.list",
50+ tableNames.sourceAuthBindings,
51+ operations.listSourceAuthBindingRows,
52+ ),
53+ upsert: (binding: SourceAuthBinding) =>
54+ toVoidEffect(
55+ backend,
56+ "rows.sourceAuthBindings.upsert",
57+ tableNames.sourceAuthBindings,
58+ () => operations.upsertSourceAuthBindingRow(binding),
59+ ),
60+ removeById: (bindingId: SourceAuthBinding["id"]) =>
61+ toBooleanEffect(
62+ backend,
63+ "rows.sourceAuthBindings.remove",
64+ tableNames.sourceAuthBindings,
65+ () => operations.removeSourceAuthBindingRowById(bindingId),
66+ ),
67+ },
68+
69+ authMaterials: {
70+ list: () =>
71+ toListEffect<AuthMaterial>(
72+ backend,
73+ "rows.authMaterials.list",
74+ tableNames.authMaterials,
75+ operations.listAuthMaterialRows,
76+ ),
77+ upsert: (material: AuthMaterial) =>
78+ toVoidEffect(
79+ backend,
80+ "rows.authMaterials.upsert",
81+ tableNames.authMaterials,
82+ () => operations.upsertAuthMaterialRow(material),
83+ ),
84+ removeByConnectionId: (connectionId: AuthMaterial["connectionId"]) =>
85+ toVoidEffect(
86+ backend,
87+ "rows.authMaterials.remove_by_connection",
88+ tableNames.authMaterials,
89+ () => operations.removeAuthMaterialRowsByConnectionId(connectionId),
90+ ),
91+ },
92+
93+ oauthStates: {
94+ list: () =>
95+ toListEffect<OAuthState>(
96+ backend,
97+ "rows.oauthStates.list",
98+ tableNames.oauthStates,
99+ operations.listOAuthStateRows,
100+ ),
101+ upsert: (state: OAuthState) =>
102+ toVoidEffect(
103+ backend,
104+ "rows.oauthStates.upsert",
105+ tableNames.oauthStates,
106+ () => operations.upsertOAuthStateRow(state),
107+ ),
108+ removeByConnectionId: (connectionId: OAuthState["connectionId"]) =>
109+ toVoidEffect(
110+ backend,
111+ "rows.oauthStates.remove_by_connection",
112+ tableNames.oauthStates,
113+ () => operations.removeOAuthStateRowsByConnectionId(connectionId),
114+ ),
115+ },
116+});
packages/persistence-sql/src/rows-effect-api-core.ts+157−0
@@ -0,0 +1,157 @@
1+import {
2+ type Approval,
3+ type Organization,
4+ type OrganizationMembership,
5+ type Policy,
6+ type Profile,
7+ type StorageInstance,
8+ type Workspace,
9+} from "@executor-v2/schema";
10+
11+import { tableNames } from "./schema";
12+import { type SqlBackend } from "./sql-internals";
13+import {
14+ type RowOperations,
15+ toBooleanEffect,
16+ toListEffect,
17+ toOptionEffect,
18+ toVoidEffect,
19+} from "./rows-effect-helpers";
20+
21+export const createCoreRowsEffectApi = (
22+ backend: SqlBackend,
23+ operations: RowOperations,
24+) => ({
25+ profile: {
26+ get: () =>
27+ toOptionEffect<Profile>(
28+ backend,
29+ "rows.profile.get",
30+ tableNames.profile,
31+ operations.getProfileRow,
32+ ),
33+ upsert: (profile: Profile) =>
34+ toVoidEffect(
35+ backend,
36+ "rows.profile.upsert",
37+ tableNames.profile,
38+ () => operations.upsertProfileRow(profile),
39+ ),
40+ },
41+
42+ organizations: {
43+ list: () =>
44+ toListEffect<Organization>(
45+ backend,
46+ "rows.organizations.list",
47+ tableNames.organizations,
48+ operations.listOrganizationsRows,
49+ ),
50+ upsert: (organization: Organization) =>
51+ toVoidEffect(
52+ backend,
53+ "rows.organizations.upsert",
54+ tableNames.organizations,
55+ () => operations.upsertOrganizationRow(organization),
56+ ),
57+ },
58+
59+ organizationMemberships: {
60+ list: () =>
61+ toListEffect<OrganizationMembership>(
62+ backend,
63+ "rows.organizationMemberships.list",
64+ tableNames.organizationMemberships,
65+ operations.listOrganizationMembershipRows,
66+ ),
67+ upsert: (membership: OrganizationMembership) =>
68+ toVoidEffect(
69+ backend,
70+ "rows.organizationMemberships.upsert",
71+ tableNames.organizationMemberships,
72+ () => operations.upsertOrganizationMembershipRow(membership),
73+ ),
74+ },
75+
76+ workspaces: {
77+ list: () =>
78+ toListEffect<Workspace>(
79+ backend,
80+ "rows.workspaces.list",
81+ tableNames.workspaces,
82+ operations.listWorkspaceRows,
83+ ),
84+ upsert: (workspace: Workspace) =>
85+ toVoidEffect(
86+ backend,
87+ "rows.workspaces.upsert",
88+ tableNames.workspaces,
89+ () => operations.upsertWorkspaceRow(workspace),
90+ ),
91+ },
92+
93+ storageInstances: {
94+ list: () =>
95+ toListEffect<StorageInstance>(
96+ backend,
97+ "rows.storageInstances.list",
98+ tableNames.storageInstances,
99+ operations.listStorageInstanceRows,
100+ ),
101+ upsert: (storageInstance: StorageInstance) =>
102+ toVoidEffect(
103+ backend,
104+ "rows.storageInstances.upsert",
105+ tableNames.storageInstances,
106+ () => operations.upsertStorageInstanceRow(storageInstance),
107+ ),
108+ removeById: (storageInstanceId: StorageInstance["id"]) =>
109+ toBooleanEffect(
110+ backend,
111+ "rows.storageInstances.remove",
112+ tableNames.storageInstances,
113+ () => operations.removeStorageInstanceRowById(storageInstanceId),
114+ ),
115+ },
116+
117+ policies: {
118+ list: () =>
119+ toListEffect<Policy>(
120+ backend,
121+ "rows.policies.list",
122+ tableNames.policies,
123+ operations.listPolicyRows,
124+ ),
125+ upsert: (policy: Policy) =>
126+ toVoidEffect(
127+ backend,
128+ "rows.policies.upsert",
129+ tableNames.policies,
130+ () => operations.upsertPolicyRow(policy),
131+ ),
132+ removeById: (policyId: Policy["id"]) =>
133+ toBooleanEffect(
134+ backend,
135+ "rows.policies.remove",
136+ tableNames.policies,
137+ () => operations.removePolicyRowById(policyId),
138+ ),
139+ },
140+
141+ approvals: {
142+ list: () =>
143+ toListEffect<Approval>(
144+ backend,
145+ "rows.approvals.list",
146+ tableNames.approvals,
147+ operations.listApprovalRows,
148+ ),
149+ upsert: (approval: Approval) =>
150+ toVoidEffect(
151+ backend,
152+ "rows.approvals.upsert",
153+ tableNames.approvals,
154+ () => operations.upsertApprovalRow(approval),
155+ ),
156+ },
157+});
packages/persistence-sql/src/rows-effect-api.ts+5−296
@@ -1,303 +1,12 @@
1−import {
2− type Approval,
3− type AuthConnection,
4− type AuthMaterial,
5− type OAuthState,
6− type Organization,
7− type OrganizationMembership,
8− type Policy,
9− type Profile,
10− type SourceAuthBinding,
11− type StorageInstance,
12− type Workspace,
13−} from "@executor-v2/schema";
14−import * as Effect from "effect/Effect";
15−import * as Option from "effect/Option";
16−
17−import { toRowStoreError } from "./persistence-errors";
18−import { createRowOperations } from "./row-operations";
19−import { tableNames } from "./schema";
1+import { createAuthRowsEffectApi } from "./rows-effect-api-auth";
2+import { createCoreRowsEffectApi } from "./rows-effect-api-core";
3+import { type RowOperations } from "./rows-effect-helpers";
204 import { type SqlBackend } from "./sql-internals";
215
22−type RowOperations = ReturnType<typeof createRowOperations>;
23−
24−const toListEffect = <A>(
25− backend: SqlBackend,
26− operation: string,
27− location: string,
28− run: () => Promise<ReadonlyArray<A>>,
29−) =>
30− Effect.tryPromise({
31− try: run,
32− catch: (cause) => toRowStoreError(backend, operation, location, cause),
33− });
34−
35−const toVoidEffect = (
36− backend: SqlBackend,
37− operation: string,
38− location: string,
39− run: () => Promise<void>,
40−) =>
41− Effect.tryPromise({
42− try: run,
43− catch: (cause) => toRowStoreError(backend, operation, location, cause),
44− });
45−
46−const toBooleanEffect = (
47− backend: SqlBackend,
48− operation: string,
49− location: string,
50− run: () => Promise<boolean>,
51−) =>
52− Effect.tryPromise({
53− try: run,
54− catch: (cause) => toRowStoreError(backend, operation, location, cause),
55− });
56−
57−const toOptionEffect = <A>(
58− backend: SqlBackend,
59− operation: string,
60− location: string,
61− run: () => Promise<A | null>,
62−) =>
63− Effect.tryPromise({
64− try: async () => {
65− const value = await run();
66− return value === null ? Option.none<A>() : Option.some(value);
67− },
68− catch: (cause) => toRowStoreError(backend, operation, location, cause),
69− });
70−
716 export const createRowsEffectApi = (
727 backend: SqlBackend,
738 operations: RowOperations,
749 ) => ({
75− profile: {
76− get: () =>
77− toOptionEffect<Profile>(
78− backend,
79− "rows.profile.get",
80− tableNames.profile,
81− operations.getProfileRow,
82− ),
83− upsert: (profile: Profile) =>
84− toVoidEffect(
85− backend,
86− "rows.profile.upsert",
87− tableNames.profile,
88− () => operations.upsertProfileRow(profile),
89− ),
90− },
91−
92− organizations: {
93− list: () =>
94− toListEffect<Organization>(
95− backend,
96− "rows.organizations.list",
97− tableNames.organizations,
98− operations.listOrganizationsRows,
99− ),
100− upsert: (organization: Organization) =>
101− toVoidEffect(
102− backend,
103− "rows.organizations.upsert",
104− tableNames.organizations,
105− () => operations.upsertOrganizationRow(organization),
106− ),
107− },
108−
109− organizationMemberships: {
110− list: () =>
111− toListEffect<OrganizationMembership>(
112− backend,
113− "rows.organizationMemberships.list",
114− tableNames.organizationMemberships,
115− operations.listOrganizationMembershipRows,
116− ),
117− upsert: (membership: OrganizationMembership) =>
118− toVoidEffect(
119− backend,
120− "rows.organizationMemberships.upsert",
121− tableNames.organizationMemberships,
122− () => operations.upsertOrganizationMembershipRow(membership),
123− ),
124− },
125−
126− workspaces: {
127− list: () =>
128− toListEffect<Workspace>(
129− backend,
130− "rows.workspaces.list",
131− tableNames.workspaces,
132− operations.listWorkspaceRows,
133− ),
134− upsert: (workspace: Workspace) =>
135− toVoidEffect(
136− backend,
137− "rows.workspaces.upsert",
138− tableNames.workspaces,
139− () => operations.upsertWorkspaceRow(workspace),
140− ),
141− },
142−
143− authConnections: {
144− list: () =>
145− toListEffect<AuthConnection>(
146− backend,
147− "rows.authConnections.list",
148− tableNames.authConnections,
149− operations.listAuthConnectionRows,
150− ),
151− upsert: (connection: AuthConnection) =>
152− toVoidEffect(
153− backend,
154− "rows.authConnections.upsert",
155− tableNames.authConnections,
156− () => operations.upsertAuthConnectionRow(connection),
157− ),
158− removeById: (connectionId: AuthConnection["id"]) =>
159− toBooleanEffect(
160− backend,
161− "rows.authConnections.remove",
162− tableNames.authConnections,
163− () => operations.removeAuthConnectionRowById(connectionId),
164− ),
165− },
166−
167− sourceAuthBindings: {
168− list: () =>
169− toListEffect<SourceAuthBinding>(
170− backend,
171− "rows.sourceAuthBindings.list",
172− tableNames.sourceAuthBindings,
173− operations.listSourceAuthBindingRows,
174− ),
175− upsert: (binding: SourceAuthBinding) =>
176− toVoidEffect(
177− backend,
178− "rows.sourceAuthBindings.upsert",
179− tableNames.sourceAuthBindings,
180− () => operations.upsertSourceAuthBindingRow(binding),
181− ),
182− removeById: (bindingId: SourceAuthBinding["id"]) =>
183− toBooleanEffect(
184− backend,
185− "rows.sourceAuthBindings.remove",
186− tableNames.sourceAuthBindings,
187− () => operations.removeSourceAuthBindingRowById(bindingId),
188− ),
189− },
190−
191− authMaterials: {
192− list: () =>
193− toListEffect<AuthMaterial>(
194− backend,
195− "rows.authMaterials.list",
196− tableNames.authMaterials,
197− operations.listAuthMaterialRows,
198− ),
199− upsert: (material: AuthMaterial) =>
200− toVoidEffect(
201− backend,
202− "rows.authMaterials.upsert",
203− tableNames.authMaterials,
204− () => operations.upsertAuthMaterialRow(material),
205− ),
206− removeByConnectionId: (connectionId: AuthMaterial["connectionId"]) =>
207− toVoidEffect(
208− backend,
209− "rows.authMaterials.remove_by_connection",
210− tableNames.authMaterials,
211− () => operations.removeAuthMaterialRowsByConnectionId(connectionId),
212− ),
213− },
214−
215− oauthStates: {
216− list: () =>
217− toListEffect<OAuthState>(
218− backend,
219− "rows.oauthStates.list",
220− tableNames.oauthStates,
221− operations.listOAuthStateRows,
222− ),
223− upsert: (state: OAuthState) =>
224− toVoidEffect(
225− backend,
226− "rows.oauthStates.upsert",
227− tableNames.oauthStates,
228− () => operations.upsertOAuthStateRow(state),
229− ),
230− removeByConnectionId: (connectionId: OAuthState["connectionId"]) =>
231− toVoidEffect(
232− backend,
233− "rows.oauthStates.remove_by_connection",
234− tableNames.oauthStates,
235− () => operations.removeOAuthStateRowsByConnectionId(connectionId),
236− ),
237− },
238−
239− storageInstances: {
240− list: () =>
241− toListEffect<StorageInstance>(
242− backend,
243− "rows.storageInstances.list",
244− tableNames.storageInstances,
245− operations.listStorageInstanceRows,
246− ),
247− upsert: (storageInstance: StorageInstance) =>
248− toVoidEffect(
249− backend,
250− "rows.storageInstances.upsert",
251− tableNames.storageInstances,
252− () => operations.upsertStorageInstanceRow(storageInstance),
253− ),
254− removeById: (storageInstanceId: StorageInstance["id"]) =>
255− toBooleanEffect(
256− backend,
257− "rows.storageInstances.remove",
258− tableNames.storageInstances,
259− () => operations.removeStorageInstanceRowById(storageInstanceId),
260− ),
261− },
262−
263− policies: {
264− list: () =>
265− toListEffect<Policy>(
266− backend,
267− "rows.policies.list",
268− tableNames.policies,
269− operations.listPolicyRows,
270− ),
271− upsert: (policy: Policy) =>
272− toVoidEffect(
273− backend,
274− "rows.policies.upsert",
275− tableNames.policies,
276− () => operations.upsertPolicyRow(policy),
277− ),
278− removeById: (policyId: Policy["id"]) =>
279− toBooleanEffect(
280− backend,
281− "rows.policies.remove",
282− tableNames.policies,
283− () => operations.removePolicyRowById(policyId),
284− ),
285− },
286−
287− approvals: {
288− list: () =>
289− toListEffect<Approval>(
290− backend,
291− "rows.approvals.list",
292− tableNames.approvals,
293− operations.listApprovalRows,
294− ),
295− upsert: (approval: Approval) =>
296− toVoidEffect(
297− backend,
298− "rows.approvals.upsert",
299− tableNames.approvals,
300− () => operations.upsertApprovalRow(approval),
301− ),
302− },
10+ ...createCoreRowsEffectApi(backend, operations),
11+ ...createAuthRowsEffectApi(backend, operations),
30312 });
packages/persistence-sql/src/rows-effect-helpers.ts+55−0
@@ -0,0 +1,55 @@
1+import * as Effect from "effect/Effect";
2+import * as Option from "effect/Option";
3+
4+import { toRowStoreError } from "./persistence-errors";
5+import { createRowOperations } from "./row-operations";
6+import { type SqlBackend } from "./sql-internals";
7+
8+export type RowOperations = ReturnType<typeof createRowOperations>;
9+
10+export const toListEffect = <A>(
11+ backend: SqlBackend,
12+ operation: string,
13+ location: string,
14+ run: () => Promise<ReadonlyArray<A>>,
15+) =>
16+ Effect.tryPromise({
17+ try: run,
18+ catch: (cause) => toRowStoreError(backend, operation, location, cause),
19+ });
20+
21+export const toVoidEffect = (
22+ backend: SqlBackend,
23+ operation: string,
24+ location: string,
25+ run: () => Promise<void>,
26+) =>
27+ Effect.tryPromise({
28+ try: run,
29+ catch: (cause) => toRowStoreError(backend, operation, location, cause),
30+ });
31+
32+export const toBooleanEffect = (
33+ backend: SqlBackend,
34+ operation: string,
35+ location: string,
36+ run: () => Promise<boolean>,
37+) =>
38+ Effect.tryPromise({
39+ try: run,
40+ catch: (cause) => toRowStoreError(backend, operation, location, cause),
41+ });
42+
43+export const toOptionEffect = <A>(
44+ backend: SqlBackend,
45+ operation: string,
46+ location: string,
47+ run: () => Promise<A | null>,
48+) =>
49+ Effect.tryPromise({
50+ try: async () => {
51+ const value = await run();
52+ return value === null ? Option.none<A>() : Option.some(value);
53+ },
54+ catch: (cause) => toRowStoreError(backend, operation, location, cause),
55+ });
packages/persistence-sql/src/schema-pg.ts+304−0
@@ -0,0 +1,304 @@
1+import {
2+ bigint,
3+ boolean,
4+ index,
5+ pgTable,
6+ primaryKey,
7+ text,
8+ uniqueIndex,
9+} from "drizzle-orm/pg-core";
10+
11+import { tableNames } from "./schema";
12+
13+export const profileTable = pgTable(tableNames.profile, {
14+ id: text("id").notNull().primaryKey(),
15+ defaultWorkspaceId: text("default_workspace_id"),
16+ displayName: text("display_name").notNull(),
17+ runtimeMode: text("runtime_mode").notNull(),
18+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
19+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
20+});
21+
22+export const organizationsTable = pgTable(tableNames.organizations, {
23+ id: text("id").notNull().primaryKey(),
24+ slug: text("slug").notNull(),
25+ name: text("name").notNull(),
26+ status: text("status").notNull(),
27+ createdByAccountId: text("created_by_account_id"),
28+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
29+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
30+});
31+
32+export const organizationMembershipsTable = pgTable(
33+ tableNames.organizationMemberships,
34+ {
35+ id: text("id").notNull().primaryKey(),
36+ organizationId: text("organization_id").notNull(),
37+ accountId: text("account_id").notNull(),
38+ role: text("role").notNull(),
39+ status: text("status").notNull(),
40+ billable: boolean("billable").notNull(),
41+ invitedByAccountId: text("invited_by_account_id"),
42+ joinedAt: bigint("joined_at", { mode: "number" }),
43+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
44+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
45+ },
46+ (table) => [
47+ index("organization_memberships_org_idx").on(table.organizationId),
48+ index("organization_memberships_account_idx").on(table.accountId),
49+ ],
50+);
51+
52+export const workspacesTable = pgTable(
53+ tableNames.workspaces,
54+ {
55+ id: text("id").notNull().primaryKey(),
56+ organizationId: text("organization_id").notNull(),
57+ name: text("name").notNull(),
58+ createdByAccountId: text("created_by_account_id"),
59+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
60+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
61+ },
62+ (table) => [
63+ index("workspaces_org_idx").on(table.organizationId),
64+ ],
65+);
66+
67+export const sourcesTable = pgTable(
68+ tableNames.sources,
69+ {
70+ workspaceId: text("workspace_id").notNull(),
71+ sourceId: text("source_id").notNull(),
72+ name: text("name").notNull(),
73+ kind: text("kind").notNull(),
74+ endpoint: text("endpoint").notNull(),
75+ status: text("status").notNull(),
76+ enabled: boolean("enabled").notNull(),
77+ configJson: text("config_json").notNull(),
78+ sourceHash: text("source_hash"),
79+ lastError: text("last_error"),
80+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
81+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
82+ },
83+ (table) => [
84+ primaryKey({
85+ columns: [table.workspaceId, table.sourceId],
86+ }),
87+ index("sources_workspace_name_idx").on(table.workspaceId, table.name),
88+ ],
89+);
90+
91+export const toolArtifactsTable = pgTable(
92+ tableNames.toolArtifacts,
93+ {
94+ id: text("id").notNull(),
95+ workspaceId: text("workspace_id").notNull(),
96+ sourceId: text("source_id").notNull(),
97+ sourceHash: text("source_hash").notNull(),
98+ toolCount: bigint("tool_count", { mode: "number" }).notNull(),
99+ manifestJson: text("manifest_json").notNull(),
100+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
101+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
102+ },
103+ (table) => [
104+ primaryKey({
105+ columns: [table.workspaceId, table.sourceId],
106+ }),
107+ uniqueIndex("tool_artifacts_id_idx").on(table.id),
108+ ],
109+);
110+
111+export const authConnectionsTable = pgTable(
112+ tableNames.authConnections,
113+ {
114+ id: text("id").notNull().primaryKey(),
115+ organizationId: text("organization_id").notNull(),
116+ workspaceId: text("workspace_id"),
117+ accountId: text("account_id"),
118+ ownerType: text("owner_type").notNull(),
119+ strategy: text("strategy").notNull(),
120+ displayName: text("display_name").notNull(),
121+ status: text("status").notNull(),
122+ statusReason: text("status_reason"),
123+ lastAuthErrorClass: text("last_auth_error_class"),
124+ metadataJson: text("metadata_json"),
125+ additionalHeadersJson: text("additional_headers_json"),
126+ createdByAccountId: text("created_by_account_id"),
127+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
128+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
129+ lastUsedAt: bigint("last_used_at", { mode: "number" }),
130+ },
131+ (table) => [
132+ index("auth_connections_org_idx").on(table.organizationId),
133+ index("auth_connections_workspace_idx").on(table.workspaceId),
134+ index("auth_connections_account_idx").on(table.accountId),
135+ ],
136+);
137+
138+export const sourceAuthBindingsTable = pgTable(
139+ tableNames.sourceAuthBindings,
140+ {
141+ id: text("id").notNull().primaryKey(),
142+ sourceId: text("source_id").notNull(),
143+ connectionId: text("connection_id").notNull(),
144+ organizationId: text("organization_id").notNull(),
145+ workspaceId: text("workspace_id"),
146+ accountId: text("account_id"),
147+ scopeType: text("scope_type").notNull(),
148+ selector: text("selector"),
149+ enabled: boolean("enabled").notNull(),
150+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
151+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
152+ },
153+ (table) => [
154+ index("source_auth_bindings_source_idx").on(table.sourceId),
155+ index("source_auth_bindings_connection_idx").on(table.connectionId),
156+ index("source_auth_bindings_org_idx").on(table.organizationId),
157+ index("source_auth_bindings_workspace_idx").on(table.workspaceId),
158+ index("source_auth_bindings_account_idx").on(table.accountId),
159+ ],
160+);
161+
162+export const authMaterialsTable = pgTable(
163+ tableNames.authMaterials,
164+ {
165+ id: text("id").notNull().primaryKey(),
166+ connectionId: text("connection_id").notNull(),
167+ ciphertext: text("ciphertext").notNull(),
168+ keyVersion: text("key_version").notNull(),
169+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
170+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
171+ },
172+ (table) => [
173+ index("auth_materials_connection_idx").on(table.connectionId),
174+ ],
175+);
176+
177+export const oauthStatesTable = pgTable(
178+ tableNames.oauthStates,
179+ {
180+ id: text("id").notNull().primaryKey(),
181+ connectionId: text("connection_id").notNull(),
182+ accessTokenCiphertext: text("access_token_ciphertext").notNull(),
183+ refreshTokenCiphertext: text("refresh_token_ciphertext"),
184+ keyVersion: text("key_version").notNull(),
185+ expiresAt: bigint("expires_at", { mode: "number" }),
186+ scope: text("scope"),
187+ tokenType: text("token_type"),
188+ issuer: text("issuer"),
189+ refreshConfigJson: text("refresh_config_json"),
190+ tokenVersion: bigint("token_version", { mode: "number" }).notNull(),
191+ leaseHolder: text("lease_holder"),
192+ leaseExpiresAt: bigint("lease_expires_at", { mode: "number" }),
193+ leaseFence: bigint("lease_fence", { mode: "number" }).notNull(),
194+ lastRefreshAt: bigint("last_refresh_at", { mode: "number" }),
195+ lastRefreshErrorClass: text("last_refresh_error_class"),
196+ lastRefreshError: text("last_refresh_error"),
197+ reauthRequiredAt: bigint("reauth_required_at", { mode: "number" }),
198+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
199+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
200+ },
201+ (table) => [
202+ index("oauth_states_connection_idx").on(table.connectionId),
203+ ],
204+);
205+
206+export const policiesTable = pgTable(
207+ tableNames.policies,
208+ {
209+ id: text("id").notNull().primaryKey(),
210+ workspaceId: text("workspace_id").notNull(),
211+ toolPathPattern: text("tool_path_pattern").notNull(),
212+ decision: text("decision").notNull(),
213+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
214+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
215+ },
216+ (table) => [
217+ index("policies_workspace_idx").on(table.workspaceId),
218+ ],
219+);
220+
221+export const approvalsTable = pgTable(
222+ tableNames.approvals,
223+ {
224+ id: text("id").notNull().primaryKey(),
225+ workspaceId: text("workspace_id").notNull(),
226+ taskRunId: text("task_run_id").notNull(),
227+ callId: text("call_id").notNull(),
228+ toolPath: text("tool_path").notNull(),
229+ status: text("status").notNull(),
230+ inputPreviewJson: text("input_preview_json").notNull(),
231+ reason: text("reason"),
232+ requestedAt: bigint("requested_at", { mode: "number" }).notNull(),
233+ resolvedAt: bigint("resolved_at", { mode: "number" }),
234+ },
235+ (table) => [
236+ index("approvals_workspace_idx").on(table.workspaceId),
237+ index("approvals_task_run_idx").on(table.taskRunId),
238+ ],
239+);
240+
241+export const taskRunsTable = pgTable(
242+ tableNames.taskRuns,
243+ {
244+ id: text("id").notNull().primaryKey(),
245+ workspaceId: text("workspace_id").notNull(),
246+ accountId: text("account_id").notNull(),
247+ sessionId: text("session_id").notNull(),
248+ runtimeId: text("runtime_id").notNull(),
249+ codeHash: text("code_hash").notNull(),
250+ status: text("status").notNull(),
251+ startedAt: bigint("started_at", { mode: "number" }),
252+ completedAt: bigint("completed_at", { mode: "number" }),
253+ exitCode: bigint("exit_code", { mode: "number" }),
254+ error: text("error"),
255+ },
256+ (table) => [
257+ index("task_runs_workspace_idx").on(table.workspaceId),
258+ ],
259+);
260+
261+export const storageInstancesTable = pgTable(
262+ tableNames.storageInstances,
263+ {
264+ id: text("id").notNull().primaryKey(),
265+ scopeType: text("scope_type").notNull(),
266+ durability: text("durability").notNull(),
267+ status: text("status").notNull(),
268+ provider: text("provider").notNull(),
269+ backendKey: text("backend_key").notNull(),
270+ organizationId: text("organization_id").notNull(),
271+ workspaceId: text("workspace_id"),
272+ accountId: text("account_id"),
273+ createdByAccountId: text("created_by_account_id"),
274+ purpose: text("purpose"),
275+ sizeBytes: bigint("size_bytes", { mode: "number" }),
276+ fileCount: bigint("file_count", { mode: "number" }),
277+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
278+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
279+ lastSeenAt: bigint("last_seen_at", { mode: "number" }).notNull(),
280+ closedAt: bigint("closed_at", { mode: "number" }),
281+ expiresAt: bigint("expires_at", { mode: "number" }),
282+ },
283+ (table) => [
284+ index("storage_instances_org_idx").on(table.organizationId),
285+ index("storage_instances_workspace_idx").on(table.workspaceId),
286+ ],
287+);
288+
289+export const syncStatesTable = pgTable(
290+ tableNames.syncStates,
291+ {
292+ id: text("id").notNull().primaryKey(),
293+ workspaceId: text("workspace_id").notNull(),
294+ target: text("target").notNull(),
295+ targetUrl: text("target_url").notNull(),
296+ linkedSubject: text("linked_subject"),
297+ cursor: text("cursor"),
298+ lastSyncAt: bigint("last_sync_at", { mode: "number" }),
299+ updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
300+ },
301+ (table) => [
302+ index("sync_states_workspace_idx").on(table.workspaceId),
303+ ],
304+);
packages/persistence-sql/src/schema.ts+212−42
@@ -23,39 +23,61 @@ export const tableNames = { · 22 unmodified lines
2323 taskRuns: "task_runs",
2424 storageInstances: "storage_instances",
2525 syncStates: "sync_states",
26− events: "events",
2726 } as const;
2827
29−const entityColumns = {
28+export const profileTable = sqliteTable(tableNames.profile, {
3029 id: text("id").notNull().primaryKey(),
31− payloadJson: text("payload_json").notNull(),
30+ defaultWorkspaceId: text("default_workspace_id"),
31+ displayName: text("display_name").notNull(),
32+ runtimeMode: text("runtime_mode").notNull(),
33+ createdAt: integer("created_at", { mode: "number" }).notNull(),
3234 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
33−};
34−
35−const workspaceEntityColumns = {
36− ...entityColumns,
37− workspaceId: text("workspace_id"),
38−};
35+});
3936
40−export const profileTable = sqliteTable(tableNames.profile, {
41− id: integer("id").notNull().primaryKey(),
42− schemaVersion: integer("schema_version").notNull(),
43− generatedAt: integer("generated_at", { mode: "number" }).notNull(),
44− profileJson: text("profile_json").notNull(),
37+export const organizationsTable = sqliteTable(tableNames.organizations, {
38+ id: text("id").notNull().primaryKey(),
39+ slug: text("slug").notNull(),
40+ name: text("name").notNull(),
41+ status: text("status").notNull(),
42+ createdByAccountId: text("created_by_account_id"),
43+ createdAt: integer("created_at", { mode: "number" }).notNull(),
4544 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
4645 });
4746
48−export const organizationsTable = sqliteTable(
49− tableNames.organizations,
50− entityColumns,
51−);
52−
5347 export const organizationMembershipsTable = sqliteTable(
5448 tableNames.organizationMemberships,
55− workspaceEntityColumns,
49+ {
50+ id: text("id").notNull().primaryKey(),
51+ organizationId: text("organization_id").notNull(),
52+ accountId: text("account_id").notNull(),
53+ role: text("role").notNull(),
54+ status: text("status").notNull(),
55+ billable: integer("billable", { mode: "boolean" }).notNull(),
56+ invitedByAccountId: text("invited_by_account_id"),
57+ joinedAt: integer("joined_at", { mode: "number" }),
58+ createdAt: integer("created_at", { mode: "number" }).notNull(),
59+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
60+ },
61+ (table) => [
62+ index("organization_memberships_org_idx").on(table.organizationId),
63+ index("organization_memberships_account_idx").on(table.accountId),
64+ ],
5665 );
5766
58−export const workspacesTable = sqliteTable(tableNames.workspaces, workspaceEntityColumns);
67+export const workspacesTable = sqliteTable(
68+ tableNames.workspaces,
69+ {
70+ id: text("id").notNull().primaryKey(),
71+ organizationId: text("organization_id").notNull(),
72+ name: text("name").notNull(),
73+ createdByAccountId: text("created_by_account_id"),
74+ createdAt: integer("created_at", { mode: "number" }).notNull(),
75+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
76+ },
77+ (table) => [
78+ index("workspaces_org_idx").on(table.organizationId),
79+ ],
80+);
5981
6082 export const sourcesTable = sqliteTable(
6183 tableNames.sources,
@@ -63,7 +85,14 @@ export const sourcesTable = sqliteTable( · 1 unmodified line
6385 workspaceId: text("workspace_id").notNull(),
6486 sourceId: text("source_id").notNull(),
6587 name: text("name").notNull(),
66− payloadJson: text("payload_json").notNull(),
88+ kind: text("kind").notNull(),
89+ endpoint: text("endpoint").notNull(),
90+ status: text("status").notNull(),
91+ enabled: integer("enabled", { mode: "boolean" }).notNull(),
92+ configJson: text("config_json").notNull(),
93+ sourceHash: text("source_hash"),
94+ lastError: text("last_error"),
95+ createdAt: integer("created_at", { mode: "number" }).notNull(),
6796 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
6897 },
6998 (table) => [
@@ -77,73 +106,214 @@ export const sourcesTable = sqliteTable( · 7 unmodified lines
77106 export const toolArtifactsTable = sqliteTable(
78107 tableNames.toolArtifacts,
79108 {
109+ id: text("id").notNull(),
80110 workspaceId: text("workspace_id").notNull(),
81111 sourceId: text("source_id").notNull(),
82− payloadJson: text("payload_json").notNull(),
112+ sourceHash: text("source_hash").notNull(),
113+ toolCount: integer("tool_count", { mode: "number" }).notNull(),
114+ manifestJson: text("manifest_json").notNull(),
115+ createdAt: integer("created_at", { mode: "number" }).notNull(),
83116 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
84117 },
85118 (table) => [
86119 primaryKey({
87120 columns: [table.workspaceId, table.sourceId],
88121 }),
122+ uniqueIndex("tool_artifacts_id_idx").on(table.id),
89123 ],
90124 );
91125
92126 export const authConnectionsTable = sqliteTable(
93127 tableNames.authConnections,
94− workspaceEntityColumns,
128+ {
129+ id: text("id").notNull().primaryKey(),
130+ organizationId: text("organization_id").notNull(),
131+ workspaceId: text("workspace_id"),
132+ accountId: text("account_id"),
133+ ownerType: text("owner_type").notNull(),
134+ strategy: text("strategy").notNull(),
135+ displayName: text("display_name").notNull(),
136+ status: text("status").notNull(),
137+ statusReason: text("status_reason"),
138+ lastAuthErrorClass: text("last_auth_error_class"),
139+ metadataJson: text("metadata_json"),
140+ additionalHeadersJson: text("additional_headers_json"),
141+ createdByAccountId: text("created_by_account_id"),
142+ createdAt: integer("created_at", { mode: "number" }).notNull(),
143+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
144+ lastUsedAt: integer("last_used_at", { mode: "number" }),
145+ },
146+ (table) => [
147+ index("auth_connections_org_idx").on(table.organizationId),
148+ index("auth_connections_workspace_idx").on(table.workspaceId),
149+ index("auth_connections_account_idx").on(table.accountId),
150+ ],
95151 );
96152
97153 export const sourceAuthBindingsTable = sqliteTable(
98154 tableNames.sourceAuthBindings,
99− workspaceEntityColumns,
155+ {
156+ id: text("id").notNull().primaryKey(),
157+ sourceId: text("source_id").notNull(),
158+ connectionId: text("connection_id").notNull(),
159+ organizationId: text("organization_id").notNull(),
160+ workspaceId: text("workspace_id"),
161+ accountId: text("account_id"),
162+ scopeType: text("scope_type").notNull(),
163+ selector: text("selector"),
164+ enabled: integer("enabled", { mode: "boolean" }).notNull(),
165+ createdAt: integer("created_at", { mode: "number" }).notNull(),
166+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
167+ },
168+ (table) => [
169+ index("source_auth_bindings_source_idx").on(table.sourceId),
170+ index("source_auth_bindings_connection_idx").on(table.connectionId),
171+ index("source_auth_bindings_org_idx").on(table.organizationId),
172+ index("source_auth_bindings_workspace_idx").on(table.workspaceId),
173+ index("source_auth_bindings_account_idx").on(table.accountId),
174+ ],
100175 );
101176
102177 export const authMaterialsTable = sqliteTable(
103178 tableNames.authMaterials,
104− workspaceEntityColumns,
179+ {
180+ id: text("id").notNull().primaryKey(),
181+ connectionId: text("connection_id").notNull(),
182+ ciphertext: text("ciphertext").notNull(),
183+ keyVersion: text("key_version").notNull(),
184+ createdAt: integer("created_at", { mode: "number" }).notNull(),
185+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
186+ },
187+ (table) => [
188+ index("auth_materials_connection_idx").on(table.connectionId),
189+ ],
105190 );
106191
107192 export const oauthStatesTable = sqliteTable(
108193 tableNames.oauthStates,
109− workspaceEntityColumns,
194+ {
195+ id: text("id").notNull().primaryKey(),
196+ connectionId: text("connection_id").notNull(),
197+ accessTokenCiphertext: text("access_token_ciphertext").notNull(),
198+ refreshTokenCiphertext: text("refresh_token_ciphertext"),
199+ keyVersion: text("key_version").notNull(),
200+ expiresAt: integer("expires_at", { mode: "number" }),
201+ scope: text("scope"),
202+ tokenType: text("token_type"),
203+ issuer: text("issuer"),
204+ refreshConfigJson: text("refresh_config_json"),
205+ tokenVersion: integer("token_version", { mode: "number" }).notNull(),
206+ leaseHolder: text("lease_holder"),
207+ leaseExpiresAt: integer("lease_expires_at", { mode: "number" }),
208+ leaseFence: integer("lease_fence", { mode: "number" }).notNull(),
209+ lastRefreshAt: integer("last_refresh_at", { mode: "number" }),
210+ lastRefreshErrorClass: text("last_refresh_error_class"),
211+ lastRefreshError: text("last_refresh_error"),
212+ reauthRequiredAt: integer("reauth_required_at", { mode: "number" }),
213+ createdAt: integer("created_at", { mode: "number" }).notNull(),
214+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
215+ },
216+ (table) => [
217+ index("oauth_states_connection_idx").on(table.connectionId),
218+ ],
110219 );
111220
112221 export const policiesTable = sqliteTable(
113222 tableNames.policies,
114− workspaceEntityColumns,
223+ {
224+ id: text("id").notNull().primaryKey(),
225+ workspaceId: text("workspace_id").notNull(),
226+ toolPathPattern: text("tool_path_pattern").notNull(),
227+ decision: text("decision").notNull(),
228+ createdAt: integer("created_at", { mode: "number" }).notNull(),
229+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
230+ },
231+ (table) => [
232+ index("policies_workspace_idx").on(table.workspaceId),
233+ ],
115234 );
116235
117236 export const approvalsTable = sqliteTable(
118237 tableNames.approvals,
119− workspaceEntityColumns,
238+ {
239+ id: text("id").notNull().primaryKey(),
240+ workspaceId: text("workspace_id").notNull(),
241+ taskRunId: text("task_run_id").notNull(),
242+ callId: text("call_id").notNull(),
243+ toolPath: text("tool_path").notNull(),
244+ status: text("status").notNull(),
245+ inputPreviewJson: text("input_preview_json").notNull(),
246+ reason: text("reason"),
247+ requestedAt: integer("requested_at", { mode: "number" }).notNull(),
248+ resolvedAt: integer("resolved_at", { mode: "number" }),
249+ },
250+ (table) => [
251+ index("approvals_workspace_idx").on(table.workspaceId),
252+ index("approvals_task_run_idx").on(table.taskRunId),
253+ ],
120254 );
121255
122256 export const taskRunsTable = sqliteTable(
123257 tableNames.taskRuns,
124− workspaceEntityColumns,
258+ {
259+ id: text("id").notNull().primaryKey(),
260+ workspaceId: text("workspace_id").notNull(),
261+ accountId: text("account_id").notNull(),
262+ sessionId: text("session_id").notNull(),
263+ runtimeId: text("runtime_id").notNull(),
264+ codeHash: text("code_hash").notNull(),
265+ status: text("status").notNull(),
266+ startedAt: integer("started_at", { mode: "number" }),
267+ completedAt: integer("completed_at", { mode: "number" }),
268+ exitCode: integer("exit_code", { mode: "number" }),
269+ error: text("error"),
270+ },
271+ (table) => [
272+ index("task_runs_workspace_idx").on(table.workspaceId),
273+ ],
125274 );
126275
127276 export const storageInstancesTable = sqliteTable(
128277 tableNames.storageInstances,
129− workspaceEntityColumns,
278+ {
279+ id: text("id").notNull().primaryKey(),
280+ scopeType: text("scope_type").notNull(),
281+ durability: text("durability").notNull(),
282+ status: text("status").notNull(),
283+ provider: text("provider").notNull(),
284+ backendKey: text("backend_key").notNull(),
285+ organizationId: text("organization_id").notNull(),
286+ workspaceId: text("workspace_id"),
287+ accountId: text("account_id"),
288+ createdByAccountId: text("created_by_account_id"),
289+ purpose: text("purpose"),
290+ sizeBytes: integer("size_bytes", { mode: "number" }),
291+ fileCount: integer("file_count", { mode: "number" }),
292+ createdAt: integer("created_at", { mode: "number" }).notNull(),
293+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
294+ lastSeenAt: integer("last_seen_at", { mode: "number" }).notNull(),
295+ closedAt: integer("closed_at", { mode: "number" }),
296+ expiresAt: integer("expires_at", { mode: "number" }),
297+ },
298+ (table) => [
299+ index("storage_instances_org_idx").on(table.organizationId),
300+ index("storage_instances_workspace_idx").on(table.workspaceId),
301+ ],
130302 );
131303
132−export const syncStatesTable = sqliteTable(tableNames.syncStates, workspaceEntityColumns);
133−
134−export const eventsTable = sqliteTable(
135− tableNames.events,
304+export const syncStatesTable = sqliteTable(
305+ tableNames.syncStates,
136306 {
137307 id: text("id").notNull().primaryKey(),
138308 workspaceId: text("workspace_id").notNull(),
139− sequence: integer("sequence").notNull(),
140− eventJson: text("event_json").notNull(),
141− createdAt: integer("created_at", { mode: "number" }).notNull(),
309+ target: text("target").notNull(),
310+ targetUrl: text("target_url").notNull(),
311+ linkedSubject: text("linked_subject"),
312+ cursor: text("cursor"),
313+ lastSyncAt: integer("last_sync_at", { mode: "number" }),
314+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
142315 },
143316 (table) => [
144− uniqueIndex("events_workspace_sequence_idx").on(
145− table.workspaceId,
146− table.sequence,
147− ),
317+ index("sync_states_workspace_idx").on(table.workspaceId),
148318 ],
149319 );
packages/persistence-sql/src/source-artifact-stores.ts+69−28
@@ -9,7 +9,6 @@ import * as Effect from "effect/Effect"; · 8 unmodified lines
99 import * as Option from "effect/Option";
1010 import { and, asc, eq } from "drizzle-orm";
1111
12−import { SourceJson, ToolArtifactJson } from "./persistence-codecs";
1312 import {
1413 toSourceStoreError,
1514 toToolArtifactStoreError,
@@ -47,6 +46,34 @@ const sortSources = (sources: ReadonlyArray<Source>): Array<Source> => · 31 unmodified lines
4746 return leftName.localeCompare(rightName);
4847 });
4948
49+const toSource = (row: DrizzleTables["sourcesTable"]["$inferSelect"]): Source => ({
50+ id: row.sourceId as Source["id"],
51+ workspaceId: row.workspaceId as Source["workspaceId"],
52+ name: row.name,
53+ kind: row.kind as Source["kind"],
54+ endpoint: row.endpoint,
55+ status: row.status as Source["status"],
56+ enabled: row.enabled,
57+ configJson: row.configJson,
58+ sourceHash: row.sourceHash,
59+ lastError: row.lastError,
60+ createdAt: row.createdAt,
61+ updatedAt: row.updatedAt,
62+});
63+
64+const toToolArtifact = (
65+ row: DrizzleTables["toolArtifactsTable"]["$inferSelect"],
66+): ToolArtifact => ({
67+ id: row.id as ToolArtifact["id"],
68+ workspaceId: row.workspaceId as ToolArtifact["workspaceId"],
69+ sourceId: row.sourceId as ToolArtifact["sourceId"],
70+ sourceHash: row.sourceHash,
71+ toolCount: row.toolCount,
72+ manifestJson: row.manifestJson,
73+ createdAt: row.createdAt,
74+ updatedAt: row.updatedAt,
75+});
76+
5077 export const createSourceAndArtifactStores = ({
5178 backend,
5279 adapter,
@@ -61,23 +88,19 @@ export const createSourceAndArtifactStores = ({ · 8 unmodified lines
6188 getById: (workspaceId: WorkspaceId, sourceId: SourceId) =>
6289 Effect.tryPromise({
6390 try: async () => {
64− const rows = await db
65− .select({ payloadJson: tables.sourcesTable.payloadJson })
66− .from(tables.sourcesTable)
67− .where(
68− and(
69− eq(tables.sourcesTable.workspaceId, workspaceId),
70− eq(tables.sourcesTable.sourceId, sourceId),
71− ),
72− )
73− .limit(1);
91+ const rows = await db.select().from(tables.sourcesTable).where(
92+ and(
93+ eq(tables.sourcesTable.workspaceId, workspaceId),
94+ eq(tables.sourcesTable.sourceId, sourceId),
95+ ),
96+ ).limit(1);
7497
7598 const row = rows[0];
7699 if (!row) {
77100 return Option.none<Source>();
78101 }
79102
80− return Option.some(SourceJson.decode(row.payloadJson));
103+ return Option.some(toSource(row));
81104 },
82105 catch: (cause) =>
83106 toSourceStoreError(backend, "get_by_id", tableNames.sources, cause),
@@ -87,12 +110,12 @@ export const createSourceAndArtifactStores = ({ · 3 unmodified lines
87110 Effect.tryPromise({
88111 try: async () => {
89112 const rows = await db
90− .select({ payloadJson: tables.sourcesTable.payloadJson })
113+ .select()
91114 .from(tables.sourcesTable)
92115 .where(eq(tables.sourcesTable.workspaceId, workspaceId))
93116 .orderBy(asc(tables.sourcesTable.name), asc(tables.sourcesTable.sourceId));
94117
95− return sortSources(rows.map((row) => SourceJson.decode(row.payloadJson)));
118+ return sortSources(rows.map(toSource));
96119 },
97120 catch: (cause) =>
98121 toSourceStoreError(backend, "list_by_workspace", tableNames.sources, cause),
@@ -104,8 +127,6 @@ export const createSourceAndArtifactStores = ({ · 5 unmodified lines
104127 await writeLocked(async () => {
105128 await adapter.transaction(async (transaction) => {
106129 const transactionContext = createDrizzleContext(transaction);
107− const payloadJson = SourceJson.encode(source);
108− const updatedAt = Date.now();
109130
110131 await transactionContext.db
111132 .insert(transactionContext.tables.sourcesTable)
@@ -113,8 +134,15 @@ export const createSourceAndArtifactStores = ({ · 1 unmodified line
113134 workspaceId: source.workspaceId,
114135 sourceId: source.id,
115136 name: source.name,
116− payloadJson,
117− updatedAt,
137+ kind: source.kind,
138+ endpoint: source.endpoint,
139+ status: source.status,
140+ enabled: source.enabled,
141+ configJson: source.configJson,
142+ sourceHash: source.sourceHash,
143+ lastError: source.lastError,
144+ createdAt: source.createdAt,
145+ updatedAt: source.updatedAt,
118146 })
119147 .onConflictDoUpdate({
120148 target: [
@@ -123,8 +151,15 @@ export const createSourceAndArtifactStores = ({ · 2 unmodified lines
123151 ],
124152 set: {
125153 name: source.name,
126− payloadJson,
127− updatedAt,
154+ kind: source.kind,
155+ endpoint: source.endpoint,
156+ status: source.status,
157+ enabled: source.enabled,
158+ configJson: source.configJson,
159+ sourceHash: source.sourceHash,
160+ lastError: source.lastError,
161+ createdAt: source.createdAt,
162+ updatedAt: source.updatedAt,
128163 },
129164 });
130165 });
@@ -177,7 +212,7 @@ export const createSourceAndArtifactStores = ({ · 46 unmodified lines
177212 Effect.tryPromise({
178213 try: async () => {
179214 const rows = await db
180− .select({ payloadJson: tables.toolArtifactsTable.payloadJson })
215+ .select()
181216 .from(tables.toolArtifactsTable)
182217 .where(
183218 and(
@@ -192,7 +227,7 @@ export const createSourceAndArtifactStores = ({ · 8 unmodified lines
192227 return Option.none<ToolArtifact>();
193228 }
194229
195− return Option.some(ToolArtifactJson.decode(row.payloadJson));
230+ return Option.some(toToolArtifact(row));
196231 },
197232 catch: (cause) =>
198233 toToolArtifactStoreError(
@@ -209,16 +244,18 @@ export const createSourceAndArtifactStores = ({ · 10 unmodified lines
209244 await writeLocked(async () => {
210245 await adapter.transaction(async (transaction) => {
211246 const transactionContext = createDrizzleContext(transaction);
212− const payloadJson = ToolArtifactJson.encode(artifact);
213− const updatedAt = Date.now();
214247
215248 await transactionContext.db
216249 .insert(transactionContext.tables.toolArtifactsTable)
217250 .values({
251+ id: artifact.id,
218252 workspaceId: artifact.workspaceId,
219253 sourceId: artifact.sourceId,
220− payloadJson,
221− updatedAt,
254+ sourceHash: artifact.sourceHash,
255+ toolCount: artifact.toolCount,
256+ manifestJson: artifact.manifestJson,
257+ createdAt: artifact.createdAt,
258+ updatedAt: artifact.updatedAt,
222259 })
223260 .onConflictDoUpdate({
224261 target: [
@@ -226,8 +263,12 @@ export const createSourceAndArtifactStores = ({ · 1 unmodified line
226263 transactionContext.tables.toolArtifactsTable.sourceId,
227264 ],
228265 set: {
229− payloadJson,
230− updatedAt,
266+ id: artifact.id,
267+ sourceHash: artifact.sourceHash,
268+ toolCount: artifact.toolCount,
269+ manifestJson: artifact.manifestJson,
270+ createdAt: artifact.createdAt,
271+ updatedAt: artifact.updatedAt,
231272 },
232273 });
233274 });
packages/persistence-sql/src/sql-internals.ts+0−418
@@ -1,418 +0,0 @@
1−import { drizzle as drizzlePgProxy } from "drizzle-orm/pg-proxy";
2−import { migrate as migratePgProxy } from "drizzle-orm/pg-proxy/migrator";
3−import { drizzle as drizzleSqliteProxy } from "drizzle-orm/sqlite-proxy";
4−import { migrate as migrateSqliteProxy } from "drizzle-orm/sqlite-proxy/migrator";
5−import { mkdir } from "node:fs/promises";
6−import { existsSync } from "node:fs";
7−import * as path from "node:path";
8−import postgres, { type Sql } from "postgres";
9−
10−import {
11− approvalsTable as approvalsSqliteTable,
12− authConnectionsTable as authConnectionsSqliteTable,
13− authMaterialsTable as authMaterialsSqliteTable,
14− oauthStatesTable as oauthStatesSqliteTable,
15− organizationMembershipsTable as organizationMembershipsSqliteTable,
16− organizationsTable as organizationsSqliteTable,
17− policiesTable as policiesSqliteTable,
18− profileTable as profileSqliteTable,
19− sourceAuthBindingsTable as sourceAuthBindingsSqliteTable,
20− sourcesTable as sourcesSqliteTable,
21− storageInstancesTable as storageInstancesSqliteTable,
22− syncStatesTable as syncStatesSqliteTable,
23− taskRunsTable as taskRunsSqliteTable,
24− toolArtifactsTable as toolArtifactsSqliteTable,
25− workspacesTable as workspacesSqliteTable,
26−} from "./schema";
27−
28−export type SqlBackend = "sqlite" | "postgres";
29−type SqlRow = Record<string, unknown>;
30−
31−export type SqlAdapter = {
32− readonly backend: SqlBackend;
33− query: <TRow extends SqlRow = SqlRow>(
34− statement: string,
35− args?: ReadonlyArray<unknown>,
36− ) => Promise<Array<TRow>>;
37− execute: (statement: string, args?: ReadonlyArray<unknown>) => Promise<void>;
38− transaction: <A>(run: (transaction: SqlAdapter) => Promise<A>) => Promise<A>;
39− close: () => Promise<void>;
40−};
41−
42−type SqliteStatement = {
43− all: (...parameters: Array<unknown>) => Array<SqlRow>;
44− run: (...parameters: Array<unknown>) => unknown;
45−};
46−
47−type GenericSqliteDatabase = {
48− exec: (statement: string) => void;
49− prepare: (statement: string) => SqliteStatement;
50− close: (...parameters: Array<unknown>) => void;
51−};
52−
53−type NodeSqliteModule = {
54− DatabaseSync: new (filename: string) => GenericSqliteDatabase;
55−};
56−
57−type BunSqliteQuery = {
58− all: (...parameters: Array<unknown>) => Array<SqlRow>;
59− run: (...parameters: Array<unknown>) => unknown;
60−};
61−
62−type BunSqliteDatabase = {
63− query: (statement: string) => BunSqliteQuery;
64− exec: (statement: string) => void;
65− close: (...parameters: Array<unknown>) => void;
66−};
67−
68−type BunSqliteModule = {
69− Database: new (
70− filename: string,
71− options?: {
72− create?: boolean;
73− readonly?: boolean;
74− },
75− ) => BunSqliteDatabase;
76−};
77−
78−const withPostgresPlaceholders = (statement: string): string => {
79− let index = 0;
80− return statement.replace(/\?/g, () => {
81− index += 1;
82− return `$${index}`;
83− });
84−};
85−
86−const isBunRuntime = (): boolean =>
87− typeof (globalThis as { Bun?: unknown }).Bun !== "undefined";
88−
89−const loadNodeSqliteModule = async (): Promise<NodeSqliteModule> => {
90− const moduleSpecifier = "node:sqlite";
91− return (await import(moduleSpecifier)) as NodeSqliteModule;
92−};
93−
94−const loadBunSqliteModule = async (): Promise<BunSqliteModule> => {
95− const moduleSpecifier = "bun:sqlite";
96− return (await import(moduleSpecifier)) as BunSqliteModule;
97−};
98−
99−const makeSqliteTransaction = (
100− execute: (statement: string, args?: ReadonlyArray<unknown>) => Promise<void>,
101− query: <TRow extends SqlRow = SqlRow>(
102− statement: string,
103− args?: ReadonlyArray<unknown>,
104− ) => Promise<Array<TRow>>,
105−): SqlAdapter["transaction"] =>
106− async <A>(run: (transactionAdapter: SqlAdapter) => Promise<A>): Promise<A> => {
107− await execute("BEGIN IMMEDIATE");
108−
109− try {
110− const adapter: SqlAdapter = {
111− backend: "sqlite",
112− query,
113− execute,
114− transaction: async (nestedRun) => nestedRun(adapter),
115− close: async () => {},
116− };
117−
118− const result = await run(adapter);
119− await execute("COMMIT");
120− return result;
121− } catch (error) {
122− try {
123− await execute("ROLLBACK");
124− } catch {
125− // ignore rollback failure after original error
126− }
127−
128− throw error;
129− }
130− };
131−
132−const createNodeSqliteAdapter = async (
133− sqlitePath: string,
134−): Promise<SqlAdapter> => {
135− const { DatabaseSync } = await loadNodeSqliteModule();
136− const db = new DatabaseSync(sqlitePath);
137−
138− const query = async <TRow extends SqlRow = SqlRow>(
139− statement: string,
140− args: ReadonlyArray<unknown> = [],
141− ): Promise<Array<TRow>> => {
142− const prepared = db.prepare(statement);
143− return prepared.all(...args) as Array<TRow>;
144− };
145−
146− const execute = async (
147− statement: string,
148− args: ReadonlyArray<unknown> = [],
149− ): Promise<void> => {
150− if (args.length === 0) {
151− db.exec(statement);
152− return;
153− }
154−
155− const prepared = db.prepare(statement);
156− prepared.run(...args);
157− };
158−
159− return {
160− backend: "sqlite",
161− query,
162− execute,
163− transaction: makeSqliteTransaction(execute, query),
164− close: async () => {
165− db.close();
166− },
167− };
168−};
169−
170−const createBunSqliteAdapter = async (
171− sqlitePath: string,
172−): Promise<SqlAdapter> => {
173− const { Database } = await loadBunSqliteModule();
174− const db = new Database(sqlitePath, { create: true });
175−
176− const query = async <TRow extends SqlRow = SqlRow>(
177− statement: string,
178− args: ReadonlyArray<unknown> = [],
179− ): Promise<Array<TRow>> => db.query(statement).all(...args) as Array<TRow>;
180−
181− const execute = async (
182− statement: string,
183− args: ReadonlyArray<unknown> = [],
184− ): Promise<void> => {
185− db.query(statement).run(...args);
186− };
187−
188− return {
189− backend: "sqlite",
190− query,
191− execute,
192− transaction: makeSqliteTransaction(execute, query),
193− close: async () => {
194− db.close();
195− },
196− };
197−};
198−
199−export const createSqliteAdapter = async (sqlitePath: string): Promise<SqlAdapter> => {
200− const resolvedPath = path.resolve(sqlitePath);
201− await mkdir(path.dirname(resolvedPath), { recursive: true });
202−
203− return isBunRuntime()
204− ? createBunSqliteAdapter(resolvedPath)
205− : createNodeSqliteAdapter(resolvedPath);
206−};
207−
208−export const createPostgresAdapter = async (
209− databaseUrl: string,
210− applicationName: string | undefined,
211−): Promise<SqlAdapter> => {
212− const client = postgres(databaseUrl, {
213− prepare: false,
214− max: 10,
215− ...(applicationName ? { connection: { application_name: applicationName } } : {}),
216− });
217−
218− type UnsafeRunner = {
219− unsafe: Sql["unsafe"];
220− };
221−
222− const toPostgresParams = (
223− args: ReadonlyArray<unknown>,
224− ): Array<postgres.ParameterOrJSON<never>> =>
225− args as unknown as Array<postgres.ParameterOrJSON<never>>;
226−
227− const queryWith = async <TRow extends SqlRow = SqlRow>(
228− runner: UnsafeRunner,
229− statement: string,
230− args: ReadonlyArray<unknown> = [],
231− ): Promise<Array<TRow>> =>
232− (await runner.unsafe(
233− withPostgresPlaceholders(statement),
234− toPostgresParams(args),
235− )) as unknown as Array<TRow>;
236−
237− const executeWith = async (
238− runner: UnsafeRunner,
239− statement: string,
240− args: ReadonlyArray<unknown> = [],
241− ): Promise<void> => {
242− await runner.unsafe(
243− withPostgresPlaceholders(statement),
244− toPostgresParams(args),
245− );
246− };
247−
248− const adapter: SqlAdapter = {
249− backend: "postgres",
250− query: (statement, args = []) => queryWith(client, statement, args),
251− execute: (statement, args = []) => executeWith(client, statement, args),
252− transaction: async <A>(run: (transaction: SqlAdapter) => Promise<A>) => {
253− const result = await client.begin(async (transactionClient) => {
254− const runner: UnsafeRunner = transactionClient;
255− const transactionAdapter: SqlAdapter = {
256− backend: "postgres",
257− query: (statement, args = []) => queryWith(runner, statement, args),
258− execute: (statement, args = []) => executeWith(runner, statement, args),
259− transaction: async (nestedRun) => nestedRun(transactionAdapter),
260− close: async () => {},
261− };
262−
263− return run(transactionAdapter);
264− });
265−
266− return result as unknown as A;
267− },
268− close: async () => {
269− await client.end({ timeout: 5 });
270− },
271− };
272−
273− return adapter;
274−};
275−
276−const resolveDrizzleMigrationsFolder = (): string => {
277− const cwd = process.cwd();
278− const candidates = [
279− path.resolve(cwd, "packages/persistence-sql/drizzle"),
280− path.resolve(cwd, "../packages/persistence-sql/drizzle"),
281− path.resolve(cwd, "../../packages/persistence-sql/drizzle"),
282− ];
283−
284− for (const candidate of candidates) {
285− if (existsSync(path.join(candidate, "meta", "_journal.json"))) {
286− return candidate;
287− }
288− }
289−
290− throw new Error("Unable to resolve drizzle migrations folder");
291−};
292−
293−const runMigrationQueries = async (
294− adapter: SqlAdapter,
295− queries: ReadonlyArray<string>,
296−): Promise<void> => {
297− for (const query of queries) {
298− const statement = query.trim();
299− if (statement.length === 0) {
300− continue;
301− }
302−
303− await adapter.execute(statement);
304− }
305−};
306−
307−const toProxyRow = (row: unknown): unknown => {
308− if (Array.isArray(row) || row === null || row === undefined) {
309− return row;
310− }
311−
312− if (typeof row === "object") {
313− return Object.values(row as Record<string, unknown>);
314− }
315−
316− return row;
317−};
318−
319−const normalizeProxyRows = (
320− method: "run" | "all" | "values" | "get",
321− rows: ReadonlyArray<unknown>,
322−): Array<unknown> => {
323− if (method === "get") {
324− const first = rows[0];
325− return first === undefined ? [] : [toProxyRow(first)];
326− }
327−
328− return rows.map(toProxyRow);
329−};
330−
331−const sqliteDrizzleSchema = {
332− profileTable: profileSqliteTable,
333− organizationsTable: organizationsSqliteTable,
334− organizationMembershipsTable: organizationMembershipsSqliteTable,
335− workspacesTable: workspacesSqliteTable,
336− sourcesTable: sourcesSqliteTable,
337− toolArtifactsTable: toolArtifactsSqliteTable,
338− authConnectionsTable: authConnectionsSqliteTable,
339− sourceAuthBindingsTable: sourceAuthBindingsSqliteTable,
340− authMaterialsTable: authMaterialsSqliteTable,
341− oauthStatesTable: oauthStatesSqliteTable,
342− policiesTable: policiesSqliteTable,
343− approvalsTable: approvalsSqliteTable,
344− taskRunsTable: taskRunsSqliteTable,
345− storageInstancesTable: storageInstancesSqliteTable,
346− syncStatesTable: syncStatesSqliteTable,
347−};
348−
349−type SqliteDrizzleSchema = typeof sqliteDrizzleSchema;
350−export type DrizzleDb = ReturnType<typeof drizzleSqliteProxy<SqliteDrizzleSchema>>;
351−export type DrizzleTables = SqliteDrizzleSchema;
352−
353−export type DrizzleContext = {
354− db: DrizzleDb;
355− tables: DrizzleTables;
356−};
357−
358−const createSqliteProxyDb = (adapter: SqlAdapter): DrizzleDb =>
359− drizzleSqliteProxy(
360− async (statement, params, method) => {
361− if (method === "run") {
362− await adapter.execute(statement, params);
363− return { rows: [] };
364− }
365−
366− const rows = await adapter.query(statement, params);
367− return {
368− rows: normalizeProxyRows(method, rows),
369− };
370− },
371− {
372− schema: sqliteDrizzleSchema,
373− },
374− );
375−
376−export const createDrizzleContext = (adapter: SqlAdapter): DrizzleContext => ({
377− db: createSqliteProxyDb(adapter),
378− tables: sqliteDrizzleSchema,
379−});
380−
381−const createPostgresMigrationDb = (adapter: SqlAdapter) =>
382− drizzlePgProxy(async (statement, params, method) => {
383− if (method === "execute") {
384− await adapter.execute(statement, params);
385− return { rows: [] };
386− }
387−
388− const rows = await adapter.query(statement, params);
389− return { rows };
390− });
391−
392−export const runMigrations = async (
393− backend: SqlBackend,
394− adapter: SqlAdapter,
395−): Promise<void> => {
396− const migrationsFolder = resolveDrizzleMigrationsFolder();
397−
398− if (backend === "postgres") {
399− const migrationDb = createPostgresMigrationDb(adapter);
400− await migratePgProxy(
401− migrationDb,
402− async (queries) => runMigrationQueries(adapter, queries),
403− {
404− migrationsFolder,
405− },
406− );
407− return;
408− }
409−
410− const migrationDb = createSqliteProxyDb(adapter);
411− await migrateSqliteProxy(
412− migrationDb,
413− async (queries) => runMigrationQueries(adapter, queries),
414− {
415− migrationsFolder,
416− },
417− );
418−};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t