History

feat(cloud): Sentry, Axiom telemetry, and observability fixes (#174)

* feat(cloud): add Sentry error tracking, Axiom telemetry, and observability fixes - Add @sentry/cloudflare wrapping fetch handler for server-side error capture - Add @sentry/react for client-side error tracking with ad-blocker tunnel - Sanitize error responses — only declared API errors pass through, everything else returns generic "Internal server error" to prevent leaking internals - Add Sentry tunnel endpoint at /api/sentry-tunnel to bypass ad blockers - Add OTEL telemetry layer exporting Effect spans to Axiom - Fix MCP session DO to use long-lived DB connection instead of request-scoped (fixes stale connection errors on tool calls) - Fix crypto.ts require() → import for Workers compatibility - Add deploy script using op run for 1Password env resolution * style: format

Rhys Sullivan committed 7 months ago

Commit d80a87c1 parent 77a9bfb10 files · +286 −43Browse files

Unified · Split

10 files
  1. apps/cloud/package.json +10 −1
  2. apps/cloud/src/api.ts +62 −5
  3. apps/cloud/src/env.ts +6 −0
  4. apps/cloud/src/mcp-session.ts +57 −31
  5. apps/cloud/src/routes/__root.tsx +11 −0
  6. apps/cloud/src/server.ts +12 −3
  7. apps/cloud/src/services/telemetry.ts +35 −0
  8. apps/cloud/wrangler.jsonc +7 −1
  9. bun.lock +85 −0
  10. packages/core/storage-postgres/src/crypto.ts +1 −2
apps/cloud/package.json+10−1
@@ -11,7 +11,7 @@ · 10 unmodified lines
11 "db:generate": "drizzle-kit generate",11 "db:generate": "drizzle-kit generate",
12 "build": "vite build",12 "build": "vite build",
13 "preview": "vite preview",13 "preview": "vite preview",
14 "deploy": "vite build && wrangler deploy",14 "deploy": "op run --env-file=.env.production -- sh -c 'vite build && wrangler deploy'",
15 "cf-typegen": "wrangler types",15 "cf-typegen": "wrangler types",
16 "typecheck": "tsgo --noEmit",16 "typecheck": "tsgo --noEmit",
17 "test": "vitest run",17 "test": "vitest run",
@@ -22,6 +22,7 @@ · 4 unmodified lines
22 "@cloudflare/vite-plugin": "^1.31.1",22 "@cloudflare/vite-plugin": "^1.31.1",
23 "@effect-atom/atom": "^0.5.0",23 "@effect-atom/atom": "^0.5.0",
24 "@effect-atom/atom-react": "^0.5.0",24 "@effect-atom/atom-react": "^0.5.0",
25 "@effect/opentelemetry": "^0.63.0",
25 "@effect/platform": "catalog:",26 "@effect/platform": "catalog:",
26 "@executor/api": "workspace:*",27 "@executor/api": "workspace:*",
27 "@executor/env": "workspace:*",28 "@executor/env": "workspace:*",
@@ -36,6 +37,14 @@ · 8 unmodified lines
36 "@executor/sdk": "workspace:*",37 "@executor/sdk": "workspace:*",
37 "@executor/storage-postgres": "workspace:*",38 "@executor/storage-postgres": "workspace:*",
38 "@modelcontextprotocol/sdk": "^1.29.0",39 "@modelcontextprotocol/sdk": "^1.29.0",
40 "@opentelemetry/exporter-logs-otlp-http": "^0.214.0",
41 "@opentelemetry/exporter-trace-otlp-http": "^0.214.0",
42 "@opentelemetry/resources": "^2.6.1",
43 "@opentelemetry/sdk-logs": "^0.214.0",
44 "@opentelemetry/sdk-trace-base": "^2.6.1",
45 "@opentelemetry/semantic-conventions": "^1.40.0",
46 "@sentry/cloudflare": "^10.48.0",
47 "@sentry/react": "^10.48.0",
39 "@tanstack/react-router": "catalog:",48 "@tanstack/react-router": "catalog:",
40 "@tanstack/react-start": "catalog:",49 "@tanstack/react-start": "catalog:",
41 "@workos-inc/node": "^8.11.1",50 "@workos-inc/node": "^8.11.1",
apps/cloud/src/api.ts+62−5
@@ -3,6 +3,7 @@ · 2 unmodified lines
3// ---------------------------------------------------------------------------3// ---------------------------------------------------------------------------
4 4
5import { env } from "cloudflare:workers";5import { env } from "cloudflare:workers";
6import * as Sentry from "@sentry/cloudflare";
6import {7import {
7 HttpApiBuilder,8 HttpApiBuilder,
8 HttpApiSwagger,9 HttpApiSwagger,
@@ -48,6 +49,7 @@ import { DbService } from "./services/db"; · 39 unmodified lines
48import { createOrgExecutor } from "./services/executor";49import { createOrgExecutor } from "./services/executor";
49import { TeamOrgApi } from "./team/compose";50import { TeamOrgApi } from "./team/compose";
50import { TeamHandlers } from "./team/handlers";51import { TeamHandlers } from "./team/handlers";
52import { TelemetryLive } from "./services/telemetry";
51import { server } from "./env";53import { server } from "./env";
52 54
53// ---------------------------------------------------------------------------55// ---------------------------------------------------------------------------
@@ -73,7 +75,7 @@ const SharedServices = Layer.mergeAll( · 19 unmodified lines
73 UserStoreLive,75 UserStoreLive,
74 WorkOSAuth.Default,76 WorkOSAuth.Default,
75 HttpServer.layerContext,77 HttpServer.layerContext,
76);78).pipe(Layer.provideMerge(TelemetryLive));
77const ProtectedCloudApiLive = HttpApiBuilder.api(ProtectedCloudApi).pipe(79const ProtectedCloudApiLive = HttpApiBuilder.api(ProtectedCloudApi).pipe(
78 Layer.provide(80 Layer.provide(
79 Layer.mergeAll(81 Layer.mergeAll(
@@ -249,6 +251,7 @@ const handleAutumnRequest = async (request: Request): Promise<Response> => { · 169 unmodified lines
249 251
250 return Effect.runPromise(program.pipe(Effect.provide(SharedServices), Effect.scoped)).catch(252 return Effect.runPromise(program.pipe(Effect.provide(SharedServices), Effect.scoped)).catch(
251 (err) => {253 (err) => {
254 Sentry.captureException(err);
252 console.error("[autumn] request failed:", err instanceof Error ? err.stack : err);255 console.error("[autumn] request failed:", err instanceof Error ? err.stack : err);
253 return Response.json({ error: "Internal server error" }, { status: 500 });256 return Response.json({ error: "Internal server error" }, { status: 500 });
254 },257 },
@@ -259,9 +262,41 @@ const handleAutumnRequest = async (request: Request): Promise<Response> => { · 4 unmodified lines
259// Widget token endpoint — returns a WorkOS widget token for the session user262// Widget token endpoint — returns a WorkOS widget token for the session user
260// ---------------------------------------------------------------------------263// ---------------------------------------------------------------------------
261 264
265// ---------------------------------------------------------------------------
266// Sentry tunnel — proxies client events to Sentry to bypass ad blockers
267// ---------------------------------------------------------------------------
268
269const SENTRY_HOST = "o4511196985556992.ingest.us.sentry.io";
270const SENTRY_PROJECT_IDS = new Set(["4511197001416704", "4511197010067456"]);
271
272const handleSentryTunnel = async (request: Request): Promise<Response> => {
273 try {
274 const body = await request.text();
275 const header = body.split("\n")[0];
276 const { dsn } = JSON.parse(header) as { dsn: string };
277 const url = new URL(dsn);
278 const projectId = url.pathname.replace("/", "");
279
280 if (url.host !== SENTRY_HOST || !SENTRY_PROJECT_IDS.has(projectId)) {
281 return new Response("Invalid Sentry DSN", { status: 400 });
282 }
283
284 return fetch(`https://${SENTRY_HOST}/api/${projectId}/envelope/`, {
285 method: "POST",
286 body,
287 });
288 } catch {
289 return new Response("Invalid request", { status: 400 });
290 }
291};
292
262export const handleApiRequest = async (request: Request): Promise<Response> => {293export const handleApiRequest = async (request: Request): Promise<Response> => {
263 const pathname = new URL(request.url).pathname;294 const pathname = new URL(request.url).pathname;
264 295
296 if (pathname === "/sentry-tunnel" && request.method === "POST") {
297 return handleSentryTunnel(request);
298 }
299
265 if (isTeamPath(pathname)) {300 if (isTeamPath(pathname)) {
266 const handler = createTeamHandler();301 const handler = createTeamHandler();
267 try {302 try {
@@ -293,6 +328,30 @@ export const handleApiRequest = async (request: Request): Promise<Response> => { · 25 unmodified lines
293 const codeExecutor = makeDynamicWorkerExecutor({ loader: env.LOADER });328 const codeExecutor = makeDynamicWorkerExecutor({ loader: env.LOADER });
294 const handler = yield* buildProtectedHandler(org.id, org.name, codeExecutor);329 const handler = yield* buildProtectedHandler(org.id, org.name, codeExecutor);
295 const response = yield* Effect.promise(() => handler.handler(request));330 const response = yield* Effect.promise(() => handler.handler(request));
331
332 // Sanitize error responses — only let declared API errors through,
333 // replace anything else with a generic message to prevent leaking internals
334 if (!response.ok) {
335 const sanitized = yield* Effect.promise(async () => {
336 try {
337 const body = await response.clone().json();
338 const hasTag = body && typeof body === "object" && "_tag" in body;
339 if (!hasTag) {
340 Sentry.captureMessage(`API ${response.status}: ${pathname}`, { level: "error" });
341 return Response.json(
342 { error: "Internal server error" },
343 { status: response.status >= 500 ? 500 : response.status },
344 );
345 }
346 } catch {
347 Sentry.captureMessage(`API ${response.status}: ${pathname}`, { level: "error" });
348 return Response.json({ error: "Internal server error" }, { status: 500 });
349 }
350 return null;
351 });
352 if (sanitized) return { response: sanitized, orgId: org.id };
353 }
354
296 return { response, orgId: org.id };355 return { response, orgId: org.id };
297 });356 });
298 357
@@ -325,10 +384,8 @@ export const handleApiRequest = async (request: Request): Promise<Response> => { · 26 unmodified lines
325 384
326 return result.response;385 return result.response;
327 } catch (err) {386 } catch (err) {
387 Sentry.captureException(err);
328 console.error("[api] request failed:", err instanceof Error ? err.stack : err);388 console.error("[api] request failed:", err instanceof Error ? err.stack : err);
329 return Response.json(389 return Response.json({ error: "Internal server error" }, { status: 500 });
330 { error: err instanceof Error ? err.message : "Internal server error" },
331 { status: 500 },
332 );
333 }390 }
334};391};
apps/cloud/src/env.ts+6−0
@@ -12,6 +12,9 @@ const serverShape = { · 11 unmodified lines
12 WORKOS_COOKIE_PASSWORD: Env.string("WORKOS_COOKIE_PASSWORD"),12 WORKOS_COOKIE_PASSWORD: Env.string("WORKOS_COOKIE_PASSWORD"),
13 VITE_PUBLIC_SITE_URL: Env.stringOr("VITE_PUBLIC_SITE_URL", ""),13 VITE_PUBLIC_SITE_URL: Env.stringOr("VITE_PUBLIC_SITE_URL", ""),
14 AUTUMN_SECRET_KEY: Env.stringOr("AUTUMN_SECRET_KEY", ""),14 AUTUMN_SECRET_KEY: Env.stringOr("AUTUMN_SECRET_KEY", ""),
15 SENTRY_DSN: Env.stringOr("SENTRY_DSN", ""),
16 AXIOM_TOKEN: Env.stringOr("AXIOM_TOKEN", ""),
17 AXIOM_DATASET: Env.stringOr("AXIOM_DATASET", "executor-cloud"),
15};18};
16 19
17type SharedEnv = Readonly<{20type SharedEnv = Readonly<{
@@ -27,6 +30,9 @@ type ServerEnv = SharedEnv & · 9 unmodified lines
27 WORKOS_COOKIE_PASSWORD: string;30 WORKOS_COOKIE_PASSWORD: string;
28 VITE_PUBLIC_SITE_URL: string;31 VITE_PUBLIC_SITE_URL: string;
29 AUTUMN_SECRET_KEY: string;32 AUTUMN_SECRET_KEY: string;
33 SENTRY_DSN: string;
34 AXIOM_TOKEN: string;
35 AXIOM_DATASET: string;
30 }>;36 }>;
31 37
32type WebEnv = Readonly<Record<string, never>>;38type WebEnv = Readonly<Record<string, never>>;
apps/cloud/src/mcp-session.ts+57−31
@@ -6,14 +6,19 @@ import { DurableObject, env } from "cloudflare:workers"; · 5 unmodified lines
6import { Data, Effect, Layer } from "effect";6import { Data, Effect, Layer } from "effect";
7import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";7import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8import { WorkerTransport, type TransportState } from "agents/mcp";8import { WorkerTransport, type TransportState } from "agents/mcp";
9import { drizzle } from "drizzle-orm/postgres-js";
10import postgres from "postgres";
9 11
10import { createExecutorMcpServer } from "@executor/host-mcp";12import { createExecutorMcpServer } from "@executor/host-mcp";
11import { makeDynamicWorkerExecutor } from "@executor/runtime-dynamic-worker";13import { makeDynamicWorkerExecutor } from "@executor/runtime-dynamic-worker";
14import type { DrizzleDb } from "@executor/storage-postgres";
15import * as sharedSchema from "@executor/storage-postgres/schema";
12 16
13import { UserStoreService } from "./auth/context";17import { UserStoreService } from "./auth/context";
14import { server } from "./env";18import { server } from "./env";
15import { createOrgExecutor } from "./services/executor";19import { createOrgExecutor } from "./services/executor";
16import { DbService } from "./services/db";20import { DbService } from "./services/db";
21import * as cloudSchema from "./services/schema";
17 22
18// ---------------------------------------------------------------------------23// ---------------------------------------------------------------------------
19// Types24// Types
@@ -23,47 +28,19 @@ export type McpSessionInit = { · 3 unmodified lines
23 organizationId: string;28 organizationId: string;
24};29};
25 30
26// Heartbeat interval — keeps the DO alive by re-scheduling an alarm before
27// Cloudflare's ~60s idle eviction kicks in.
28const HEARTBEAT_MS = 30 * 1000;31const HEARTBEAT_MS = 30 * 1000;
29
30// Session timeout — clean up after no requests for this long.
31// TODO: Make tier-based — free users get 60s, paid users get 5 minutes.
32const SESSION_TIMEOUT_MS = 5 * 60 * 1000;32const SESSION_TIMEOUT_MS = 5 * 60 * 1000;
33 33
34// ---------------------------------------------------------------------------34// ---------------------------------------------------------------------------
35// Session initialization effect35// Errors
36// ---------------------------------------------------------------------------36// ---------------------------------------------------------------------------
37 37
38const DbLive = DbService.Live;
39const UserStoreLive = UserStoreService.Live.pipe(Layer.provide(DbLive));
40const Services = Layer.mergeAll(DbLive, UserStoreLive);
41
42class OrganizationNotFoundError extends Data.TaggedError("OrganizationNotFoundError")<{38class OrganizationNotFoundError extends Data.TaggedError("OrganizationNotFoundError")<{
43 readonly organizationId: string;39 readonly organizationId: string;
44}> {}40}> {}
45 41
46const initSession = (organizationId: string) =>
47 Effect.gen(function* () {
48 const users = yield* UserStoreService;
49 const org = yield* users.use((store) => store.getOrganization(organizationId));
50
51 if (!org) {
52 return yield* new OrganizationNotFoundError({ organizationId });
53 }
54
55 const executor = yield* createOrgExecutor(org.id, org.name, server.ENCRYPTION_KEY);
56
57 const codeExecutor = makeDynamicWorkerExecutor({ loader: env.LOADER });
58 const mcpServer = yield* Effect.promise(() =>
59 createExecutorMcpServer({ executor, codeExecutor }),
60 );
61
62 return mcpServer;
63 }).pipe(Effect.provide(Services));
64
65// ---------------------------------------------------------------------------42// ---------------------------------------------------------------------------
66// JSON-RPC error response helper43// Helpers
67// ---------------------------------------------------------------------------44// ---------------------------------------------------------------------------
68 45
69const jsonRpcError = (status: number, code: number, message: string) =>46const jsonRpcError = (status: number, code: number, message: string) =>
@@ -72,6 +49,32 @@ const jsonRpcError = (status: number, code: number, message: string) => · 2 unmodified lines
72 headers: { "content-type": "application/json" },49 headers: { "content-type": "application/json" },
73 });50 });
74 51
52const combinedSchema = { ...sharedSchema, ...cloudSchema };
53
54/**
55 * Create a long-lived DB connection for the DO lifetime.
56 *
57 * Unlike the per-request `DbService.Live` used in `api.ts`, this connection
58 * stays open across requests within the DO. DOs have a single-threaded
59 * execution model — there's no cross-request socket reuse issue because
60 * only one request runs at a time. The connection is closed when the DO
61 * cleans up (timeout or eviction).
62 */
63const makeLongLivedDb = (): { db: DrizzleDb; end: () => Promise<void> } => {
64 const connectionString = env.HYPERDRIVE?.connectionString ?? server.DATABASE_URL;
65 const sql = postgres(connectionString, {
66 max: 1,
67 idle_timeout: 20,
68 max_lifetime: 300,
69 connect_timeout: 10,
70 onnotice: () => undefined,
71 });
72 return {
73 db: drizzle(sql, { schema: combinedSchema }) as DrizzleDb,
74 end: () => sql.end({ timeout: 0 }).catch(() => undefined),
75 };
76};
77
75// ---------------------------------------------------------------------------78// ---------------------------------------------------------------------------
76// Durable Object79// Durable Object
77// ---------------------------------------------------------------------------80// ---------------------------------------------------------------------------
@@ -81,6 +84,7 @@ export class McpSessionDO extends DurableObject { · 3 unmodified lines
81 private transport: WorkerTransport | null = null;84 private transport: WorkerTransport | null = null;
82 private initialized = false;85 private initialized = false;
83 private lastActivityMs = 0;86 private lastActivityMs = 0;
87 private dbHandle: { db: DrizzleDb; end: () => Promise<void> } | null = null;
84 88
85 private makeStorage() {89 private makeStorage() {
86 return {90 return {
@@ -96,7 +100,25 @@ export class McpSessionDO extends DurableObject { · 9 unmodified lines
96 async init(token: McpSessionInit): Promise<void> {100 async init(token: McpSessionInit): Promise<void> {
97 if (this.initialized) return;101 if (this.initialized) return;
98 102
99 this.mcpServer = await Effect.runPromise(initSession(token.organizationId));103 // Create a long-lived DB connection for the DO's lifetime
104 this.dbHandle = makeLongLivedDb();
105
106 const DbLive = Layer.succeed(DbService, this.dbHandle.db);
107 const UserStoreLive = UserStoreService.Live.pipe(Layer.provide(DbLive));
108 const Services = Layer.mergeAll(DbLive, UserStoreLive);
109
110 const program = Effect.gen(function* () {
111 const users = yield* UserStoreService;
112 const org = yield* users.use((store) => store.getOrganization(token.organizationId));
113 if (!org)
114 return yield* new OrganizationNotFoundError({ organizationId: token.organizationId });
115
116 const executor = yield* createOrgExecutor(org.id, org.name, server.ENCRYPTION_KEY);
117 const codeExecutor = makeDynamicWorkerExecutor({ loader: env.LOADER });
118 return yield* Effect.promise(() => createExecutorMcpServer({ executor, codeExecutor }));
119 }).pipe(Effect.provide(Services));
120
121 this.mcpServer = await Effect.runPromise(program);
100 122
101 this.transport = new WorkerTransport({123 this.transport = new WorkerTransport({
102 sessionIdGenerator: () => this.ctx.id.toString(),124 sessionIdGenerator: () => this.ctx.id.toString(),
@@ -143,6 +165,10 @@ export class McpSessionDO extends DurableObject { · 40 unmodified lines
143 await this.mcpServer.close().catch(() => undefined);165 await this.mcpServer.close().catch(() => undefined);
144 this.mcpServer = null;166 this.mcpServer = null;
145 }167 }
168 if (this.dbHandle) {
169 await this.dbHandle.end();
170 this.dbHandle = null;
171 }
146 this.initialized = false;172 this.initialized = false;
147 }173 }
148}174}
apps/cloud/src/routes/__root.tsx+11−0
@@ -1,4 +1,5 @@
1import React from "react";1import React from "react";
2import * as Sentry from "@sentry/react";
2import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router";3import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router";
3import { AutumnProvider } from "autumn-js/react";4import { AutumnProvider } from "autumn-js/react";
4import { ExecutorProvider } from "@executor/react/api/provider";5import { ExecutorProvider } from "@executor/react/api/provider";
@@ -8,6 +9,16 @@ import { LoginPage } from "../web/pages/login"; · 3 unmodified lines
8import { Shell } from "../web/shell";9import { Shell } from "../web/shell";
9import appCss from "@executor/react/globals.css?url";10import appCss from "@executor/react/globals.css?url";
10 11
12if (typeof window !== "undefined" && import.meta.env.VITE_PUBLIC_SENTRY_DSN) {
13 Sentry.init({
14 dsn: import.meta.env.VITE_PUBLIC_SENTRY_DSN,
15 tunnel: "/api/sentry-tunnel",
16 tracesSampleRate: 0,
17 replaysSessionSampleRate: 0.1,
18 replaysOnErrorSampleRate: 1.0,
19 });
20}
21
11export const Route = createRootRoute({22export const Route = createRootRoute({
12 head: () => ({23 head: () => ({
13 meta: [24 meta: [
apps/cloud/src/server.ts+12−3
@@ -1,8 +1,17 @@
1import * as Sentry from "@sentry/cloudflare";
1import handler from "@tanstack/react-start/server-entry";2import handler from "@tanstack/react-start/server-entry";
2 3
3// Export Durable Objects as named exports4// Export Durable Objects as named exports
4export { McpSessionDO } from "./mcp-session";5export { McpSessionDO } from "./mcp-session";
5 6
6export default {7export default Sentry.withSentry(
7 fetch: handler.fetch,8 (env: Record<string, string>) => ({
8};9 dsn: env.SENTRY_DSN,
10 tracesSampleRate: 0,
11 enableLogs: true,
12 sendDefaultPii: true,
13 }),
14 {
15 fetch: handler.fetch,
16 },
17);
apps/cloud/src/services/telemetry.ts+35−0
@@ -0,0 +1,35 @@
1// ---------------------------------------------------------------------------
2// OpenTelemetry setup — pipes Effect spans + logs to Axiom via OTLP
3// ---------------------------------------------------------------------------
4
5import { Layer } from "effect";
6import { WebSdk, Tracer as OtelTracer } from "@effect/opentelemetry";
7import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
8import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
9import { server } from "../env";
10
11const makeResourceLayer = () =>
12 WebSdk.layer(() => ({
13 resource: {
14 serviceName: "executor-cloud",
15 serviceVersion: "1.0.0",
16 },
17 spanProcessor: new BatchSpanProcessor(
18 new OTLPTraceExporter({
19 url: "https://api.axiom.co/v1/traces",
20 headers: {
21 Authorization: `Bearer ${server.AXIOM_TOKEN}`,
22 "X-Axiom-Dataset": server.AXIOM_DATASET,
23 },
24 }),
25 ),
26 }));
27
28/**
29 * Full telemetry layer — provides Effect Tracer backed by OTEL → Axiom.
30 * All existing `Effect.withSpan` calls automatically become distributed traces.
31 * No-op when AXIOM_TOKEN is not set.
32 */
33export const TelemetryLive: Layer.Layer<never> = server.AXIOM_TOKEN
34 ? OtelTracer.layerGlobal.pipe(Layer.provide(makeResourceLayer()))
35 : Layer.empty;
apps/cloud/wrangler.jsonc+7−1
@@ -4,7 +4,12 @@ · 3 unmodified lines
4 "compatibility_date": "2025-04-01",4 "compatibility_date": "2025-04-01",
5 "compatibility_flags": ["nodejs_compat"],5 "compatibility_flags": ["nodejs_compat"],
6 "main": "src/server.ts",6 "main": "src/server.ts",
7 "routes": [{ "pattern": "executor.sh", "custom_domain": true }],7 "routes": [
8 {
9 "pattern": "executor.sh",
10 "custom_domain": true,
11 },
12 ],
8 "limits": {13 "limits": {
9 "cpu_ms": 300000,14 "cpu_ms": 300000,
10 },15 },
@@ -44,6 +49,7 @@ · 33 unmodified lines
44 },49 },
45 ],50 ],
46 "vars": {51 "vars": {
52 "VITE_PUBLIC_SENTRY_DSN": "https://e20b1bdeea27008092a4dc0ac303e97a@o4511196985556992.ingest.us.sentry.io/4511197010067456",
47 "VITE_PUBLIC_SITE_URL": "https://executor.sh",53 "VITE_PUBLIC_SITE_URL": "https://executor.sh",
48 },54 },
49}55}
bun.lock+85−0
@@ -48,6 +48,7 @@ · 47 unmodified lines
48 "@cloudflare/vite-plugin": "^1.31.1",48 "@cloudflare/vite-plugin": "^1.31.1",
49 "@effect-atom/atom": "^0.5.0",49 "@effect-atom/atom": "^0.5.0",
50 "@effect-atom/atom-react": "^0.5.0",50 "@effect-atom/atom-react": "^0.5.0",
51 "@effect/opentelemetry": "^0.63.0",
51 "@effect/platform": "catalog:",52 "@effect/platform": "catalog:",
52 "@executor/api": "workspace:*",53 "@executor/api": "workspace:*",
53 "@executor/env": "workspace:*",54 "@executor/env": "workspace:*",
@@ -62,6 +63,14 @@ · 8 unmodified lines
62 "@executor/sdk": "workspace:*",63 "@executor/sdk": "workspace:*",
63 "@executor/storage-postgres": "workspace:*",64 "@executor/storage-postgres": "workspace:*",
64 "@modelcontextprotocol/sdk": "^1.29.0",65 "@modelcontextprotocol/sdk": "^1.29.0",
66 "@opentelemetry/exporter-logs-otlp-http": "^0.214.0",
67 "@opentelemetry/exporter-trace-otlp-http": "^0.214.0",
68 "@opentelemetry/resources": "^2.6.1",
69 "@opentelemetry/sdk-logs": "^0.214.0",
70 "@opentelemetry/sdk-trace-base": "^2.6.1",
71 "@opentelemetry/semantic-conventions": "^1.40.0",
72 "@sentry/cloudflare": "^10.48.0",
73 "@sentry/react": "^10.48.0",
65 "@tanstack/react-router": "catalog:",74 "@tanstack/react-router": "catalog:",
66 "@tanstack/react-start": "catalog:",75 "@tanstack/react-start": "catalog:",
67 "@workos-inc/node": "^8.11.1",76 "@workos-inc/node": "^8.11.1",
@@ -885,6 +894,8 @@ · 817 unmodified lines
885 894
886 "@effect/language-service": ["@effect/language-service@0.84.3", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-zpxi6rLCwst/cBQd7ElwDvt36Y6Jvz8v6bCLnNiOL6OXvdLmqjOFWyzWZdMh92vvBQA/aVKhfIAAOP3o4wKt0A=="],895 "@effect/language-service": ["@effect/language-service@0.84.3", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-zpxi6rLCwst/cBQd7ElwDvt36Y6Jvz8v6bCLnNiOL6OXvdLmqjOFWyzWZdMh92vvBQA/aVKhfIAAOP3o4wKt0A=="],
887 896
897 "@effect/opentelemetry": ["@effect/opentelemetry@0.63.0", "", { "peerDependencies": { "@effect/platform": "^0.96.0", "@opentelemetry/api": "^1.9", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", "@opentelemetry/sdk-trace-node": "^2.0.0", "@opentelemetry/sdk-trace-web": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.33.0", "effect": "^3.21.0" } }, "sha512-2yUG2QWNATi1uKP0kwhaP5eLp+c5NDzAL3EOpIcGLBAC0cbXZrx4n9Qw/QwUKxpuV+pbhrBUPCiByyWAFKfuCw=="],
898
888 "@effect/platform": ["@effect/platform@0.96.0", "", { "dependencies": { "find-my-way-ts": "^0.1.6", "msgpackr": "^1.11.4", "multipasta": "^0.2.7" }, "peerDependencies": { "effect": "^3.21.0" } }, "sha512-U7PLhkVzg7zzrgFvyWATOzD6reL87KG/fcdOxgLWBQ/J5CCU6qdPAVG+0o6o+IxcsLoqGwxs+rFxaFzrdtDV1A=="],899 "@effect/platform": ["@effect/platform@0.96.0", "", { "dependencies": { "find-my-way-ts": "^0.1.6", "msgpackr": "^1.11.4", "multipasta": "^0.2.7" }, "peerDependencies": { "effect": "^3.21.0" } }, "sha512-U7PLhkVzg7zzrgFvyWATOzD6reL87KG/fcdOxgLWBQ/J5CCU6qdPAVG+0o6o+IxcsLoqGwxs+rFxaFzrdtDV1A=="],
889 900
890 "@effect/platform-bun": ["@effect/platform-bun@0.89.0", "", { "dependencies": { "@effect/platform-node-shared": "^0.59.0", "multipasta": "^0.2.7" }, "peerDependencies": { "@effect/cluster": "^0.58.0", "@effect/platform": "^0.96.0", "@effect/rpc": "^0.75.0", "@effect/sql": "^0.51.0", "effect": "^3.21.0" } }, "sha512-ReT5f2vujJfffMOBexrgwJd2RLxgfr2G0c1FyCsoflcjdQJ7RZE3cwHDp1M3hAzmG67wWAssMHqLsX6H/n27sQ=="],901 "@effect/platform-bun": ["@effect/platform-bun@0.89.0", "", { "dependencies": { "@effect/platform-node-shared": "^0.59.0", "multipasta": "^0.2.7" }, "peerDependencies": { "@effect/cluster": "^0.58.0", "@effect/platform": "^0.96.0", "@effect/rpc": "^0.75.0", "@effect/sql": "^0.51.0", "effect": "^3.21.0" } }, "sha512-ReT5f2vujJfffMOBexrgwJd2RLxgfr2G0c1FyCsoflcjdQJ7RZE3cwHDp1M3hAzmG67wWAssMHqLsX6H/n27sQ=="],
@@ -1215,6 +1226,32 @@ · 324 unmodified lines
1215 1226
1216 "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],1227 "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
1217 1228
1229 "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.214.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA=="],
1230
1231 "@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.6.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-XHzhwRNkBpeP8Fs/qjGrAf9r9PRv67wkJQ/7ZPaBQQ68DYlTBBx5MF9LvPx7mhuXcDessKK2b+DcxqwpgkcivQ=="],
1232
1233 "@opentelemetry/core": ["@opentelemetry/core@2.6.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g=="],
1234
1235 "@opentelemetry/exporter-logs-otlp-http": ["@opentelemetry/exporter-logs-otlp-http@0.214.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.214.0", "@opentelemetry/core": "2.6.1", "@opentelemetry/otlp-exporter-base": "0.214.0", "@opentelemetry/otlp-transformer": "0.214.0", "@opentelemetry/sdk-logs": "0.214.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-9qv2Tl/Hq6qc5pJCbzFJnzA0uvlb9DgM70yGJPYf3bA5LlLkRCpcn81i4JbcIH4grlQIWY6A+W7YG0LLvS1BAw=="],
1236
1237 "@opentelemetry/exporter-trace-otlp-http": ["@opentelemetry/exporter-trace-otlp-http@0.214.0", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/otlp-exporter-base": "0.214.0", "@opentelemetry/otlp-transformer": "0.214.0", "@opentelemetry/resources": "2.6.1", "@opentelemetry/sdk-trace-base": "2.6.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-kIN8nTBMgV2hXzV/a20BCFilPZdAIMYYJGSgfMMRm/Xa+07y5hRDS2Vm12A/z8Cdu3Sq++ZvJfElokX2rkgGgw=="],
1238
1239 "@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.214.0", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/otlp-transformer": "0.214.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-u1Gdv0/E9wP+apqWf7Wv2npXmgJtxsW2XL0TEv9FZloTZRuMBKmu8cYVXwS4Hm3q/f/3FuCnPTgiwYvIqRSpRg=="],
1240
1241 "@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.214.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.214.0", "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/sdk-logs": "0.214.0", "@opentelemetry/sdk-metrics": "2.6.1", "@opentelemetry/sdk-trace-base": "2.6.1", "protobufjs": "^7.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-DSaYcuBRh6uozfsWN3R8HsN0yDhCuWP7tOFdkUOVaWD1KVJg8m4qiLUsg/tNhTLS9HUYUcwNpwL2eroLtsZZ/w=="],
1242
1243 "@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="],
1244
1245 "@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.214.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.214.0", "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-zf6acnScjhsaBUU22zXZ/sLWim1dfhUAbGXdMmHmNG3LfBnQ3DKsOCITb2IZwoUsNNMTogqFKBnlIPPftUgGwA=="],
1246
1247 "@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-9t9hJHX15meBy2NmTJxL+NJfXmnausR2xUDvE19XQce0Qi/GBtDGamU8nS1RMbdgDmhgpm3VaOu2+fiS/SfTpQ=="],
1248
1249 "@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-r86ut4T1e8vNwB35CqCcKd45yzqH6/6Wzvpk2/cZB8PsPLlZFTvrh8yfOS3CYZYcUmAx4hHTZJ8AO8Dj8nrdhw=="],
1250
1251 "@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@2.6.1", "", { "dependencies": { "@opentelemetry/context-async-hooks": "2.6.1", "@opentelemetry/core": "2.6.1", "@opentelemetry/sdk-trace-base": "2.6.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-Hh2i4FwHWRFhnO2Q/p6svMxy8MPsNCG0uuzUY3glqm0rwM0nQvbTO1dXSp9OqQoTKXcQzaz9q1f65fsurmOhNw=="],
1252
1253 "@opentelemetry/sdk-trace-web": ["@opentelemetry/sdk-trace-web@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/sdk-trace-base": "2.6.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-JQevIjBlWGcKBfuwe7tdxGR/75RERsf1OOIvUzPKq86J8qhzkyjnLTTuPNPLRQF1xxEe65W5aI1Uwl6yWUGPQQ=="],
1254
1218 "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="],1255 "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="],
1219 1256
1220 "@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="],1257 "@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="],
@@ -1413,6 +1450,26 @@ · 192 unmodified lines
1413 1450
1414 "@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="],1451 "@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="],
1415 1452
1453 "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="],
1454
1455 "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="],
1456
1457 "@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="],
1458
1459 "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="],
1460
1461 "@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="],
1462
1463 "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="],
1464
1465 "@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="],
1466
1467 "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="],
1468
1469 "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="],
1470
1471 "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="],
1472
1416 "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],1473 "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
1417 1474
1418 "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],1475 "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
@@ -1637,6 +1694,22 @@ · 218 unmodified lines
1637 1694
1638 "@secure-exec/v8-linux-x64-gnu": ["@secure-exec/v8-linux-x64-gnu@0.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-Az4s+vUf+78vWtsC7rTn/jQc6WKJafAdt2YpEjB4Gnu+sX+FFTIst1hRV4gJonbRyJdy6SW+OQ6DZatmwczorQ=="],1695 "@secure-exec/v8-linux-x64-gnu": ["@secure-exec/v8-linux-x64-gnu@0.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-Az4s+vUf+78vWtsC7rTn/jQc6WKJafAdt2YpEjB4Gnu+sX+FFTIst1hRV4gJonbRyJdy6SW+OQ6DZatmwczorQ=="],
1639 1696
1697 "@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.48.0", "", { "dependencies": { "@sentry/core": "10.48.0" } }, "sha512-SCiTLBXzugFKxev6NoKYBIhQoDk0gUh0AVVVepCBqfCJiWBG01Zvv0R5tCVohr4cWRllkQ8mlBdNQd/I7s9tdA=="],
1698
1699 "@sentry-internal/feedback": ["@sentry-internal/feedback@10.48.0", "", { "dependencies": { "@sentry/core": "10.48.0" } }, "sha512-tGkEyOM1HDS9qebDphUMEnyk3qq/50AnuTBiFmMJyjNzowylVGmRRk0sr3xkmbVHCDXQCiYnDmSVlJ2x4SDMrQ=="],
1700
1701 "@sentry-internal/replay": ["@sentry-internal/replay@10.48.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.48.0", "@sentry/core": "10.48.0" } }, "sha512-sevRTePfuk4PNuz9KAKpmTZEomAU0aLXyIhOwA0OnUDdxPhkY8kq5lwDbuxTHv6DQUjUX3YgFbY45VH1JEqHKA=="],
1702
1703 "@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.48.0", "", { "dependencies": { "@sentry-internal/replay": "10.48.0", "@sentry/core": "10.48.0" } }, "sha512-9nWuN2z4O+iwbTfuYV5ZmngBgJU/ZxfOo47A5RJP3Nu/kl59aJ1lUhILYOKyeNOIC/JyeERmpIcTxnlPXQzZ3Q=="],
1704
1705 "@sentry/browser": ["@sentry/browser@10.48.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.48.0", "@sentry-internal/feedback": "10.48.0", "@sentry-internal/replay": "10.48.0", "@sentry-internal/replay-canvas": "10.48.0", "@sentry/core": "10.48.0" } }, "sha512-4jt2zX2ExgFcNe2x+W+/k81fmDUsOrquGtt028CiGuDuma6kEsWBI4JbooT1jhj2T+eeUxe3YGbM23Zhh7Ghhw=="],
1706
1707 "@sentry/cloudflare": ["@sentry/cloudflare@10.48.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.1", "@sentry/core": "10.48.0" }, "peerDependencies": { "@cloudflare/workers-types": "^4.x" }, "optionalPeers": ["@cloudflare/workers-types"] }, "sha512-i02Ps4/cJjFpbcHLMhNEFXTeVqLB9XpB3+/OFQ9aMFV3yDcxlvHwe0oo7WZf41iroArvpysotLG8Y8NBOU9omA=="],
1708
1709 "@sentry/core": ["@sentry/core@10.48.0", "", {}, "sha512-h8F+fXVwYC9ro5ZaO8V+v3vqc0awlXHGblEAuVxSGgh4IV/oFX+QVzXeDTTrFOFS6v/Vn5vAyu240eJrJAS6/g=="],
1710
1711 "@sentry/react": ["@sentry/react@10.48.0", "", { "dependencies": { "@sentry/browser": "10.48.0", "@sentry/core": "10.48.0" }, "peerDependencies": { "react": "^16.14.0 || 17.x || 18.x || 19.x" } }, "sha512-uc93vKjmu6gNns+JAX4qquuxWpAMit0uGPA1TYlMjct9NG1uX3TkDPJAr9Pgd1lOXx8mKqCmj5fK33QeExMpPw=="],
1712
1640 "@shikijs/core": ["@shikijs/core@4.0.2", "", { "dependencies": { "@shikijs/primitive": "4.0.2", "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw=="],1713 "@shikijs/core": ["@shikijs/core@4.0.2", "", { "dependencies": { "@shikijs/primitive": "4.0.2", "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw=="],
1641 1714
1642 "@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-7PW0Nm49DcoUIQEXlJhNNBHyoGMjalRETTCcjMqEaMoJRLljy1Bi/EGV3/qLBgLKQejdspiiYuHGQW6dX94Nag=="],1715 "@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-7PW0Nm49DcoUIQEXlJhNNBHyoGMjalRETTCcjMqEaMoJRLljy1Bi/EGV3/qLBgLKQejdspiiYuHGQW6dX94Nag=="],
@@ -2841,6 +2914,8 @@ · 1198 unmodified lines
2841 2914
2842 "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="],2915 "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="],
2843 2916
2917 "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
2918
2844 "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],2919 "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
2845 2920
2846 "lookpath": ["lookpath@1.2.3", "", { "bin": { "lookpath": "bin/lookpath.js" } }, "sha512-kthRVhf4kH4+HW3anM4UBHxsw/XFESf13euCEldhXr6GpBdmBoa7rDd7WO5G0Mhd4G5XtKTcEy8OR0iRZXpS3Q=="],2921 "lookpath": ["lookpath@1.2.3", "", { "bin": { "lookpath": "bin/lookpath.js" } }, "sha512-kthRVhf4kH4+HW3anM4UBHxsw/XFESf13euCEldhXr6GpBdmBoa7rDd7WO5G0Mhd4G5XtKTcEy8OR0iRZXpS3Q=="],
@@ -3251,6 +3326,8 @@ · 404 unmodified lines
3251 3326
3252 "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],3327 "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
3253 3328
3329 "protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
3330
3254 "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],3331 "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
3255 3332
3256 "public-encrypt": ["public-encrypt@4.0.3", "", { "dependencies": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" } }, "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q=="],3333 "public-encrypt": ["public-encrypt@4.0.3", "", { "dependencies": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" } }, "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q=="],
@@ -3905,6 +3982,8 @@ · 648 unmodified lines
3905 3982
3906 "@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],3983 "@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
3907 3984
3985 "@opentelemetry/api-logs/@opentelemetry/api": ["@opentelemetry/api@1.9.1", "", {}, "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q=="],
3986
3908 "@poppinss/colors/kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],3987 "@poppinss/colors/kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
3909 3988
3910 "@poppinss/dumper/@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="],3989 "@poppinss/dumper/@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="],
@@ -4001,6 +4080,8 @@ · 90 unmodified lines
4001 4080
4002 "@secure-exec/nodejs/esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="],4081 "@secure-exec/nodejs/esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="],
4003 4082
4083 "@sentry/cloudflare/@opentelemetry/api": ["@opentelemetry/api@1.9.1", "", {}, "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q=="],
4084
4004 "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="],4085 "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="],
4005 4086
4006 "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="],4087 "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="],
@@ -4175,6 +4256,8 @@ · 168 unmodified lines
4175 4256
4176 "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],4257 "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
4177 4258
4259 "protobufjs/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="],
4260
4178 "public-encrypt/bn.js": ["bn.js@4.12.3", "", {}, "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g=="],4261 "public-encrypt/bn.js": ["bn.js@4.12.3", "", {}, "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g=="],
4179 4262
4180 "radix-ui/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],4263 "radix-ui/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
@@ -4555,6 +4638,8 @@ · 374 unmodified lines
4555 4638
4556 "pkg-dir/find-up/locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],4639 "pkg-dir/find-up/locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
4557 4640
4641 "protobufjs/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
4642
4558 "read-yaml-file/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],4643 "read-yaml-file/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
4559 4644
4560 "ripemd160/hash-base/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],4645 "ripemd160/hash-base/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
packages/core/storage-postgres/src/crypto.ts+1−2
@@ -1,4 +1,4 @@
1import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";1import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
2 2
3const ALGORITHM = "aes-256-gcm";3const ALGORITHM = "aes-256-gcm";
4const IV_LENGTH = 12;4const IV_LENGTH = 12;
@@ -9,7 +9,6 @@ const AUTH_TAG_LENGTH = 16; · 4 unmodified lines
9 * Uses SHA-256 to normalize any length input to exactly 32 bytes.9 * Uses SHA-256 to normalize any length input to exactly 32 bytes.
10 */10 */
11const deriveKey = (key: string): Buffer => {11const deriveKey = (key: string): Buffer => {
12 const { createHash } = require("node:crypto") as typeof import("node:crypto");
13 return createHash("sha256").update(key).digest();12 return createHash("sha256").update(key).digest();
14};13};
15 14

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