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
1111 "db:generate": "drizzle-kit generate",
1212 "build": "vite build",
1313 "preview": "vite preview",
14− "deploy": "vite build && wrangler deploy",
14+ "deploy": "op run --env-file=.env.production -- sh -c 'vite build && wrangler deploy'",
1515 "cf-typegen": "wrangler types",
1616 "typecheck": "tsgo --noEmit",
1717 "test": "vitest run",
@@ -22,6 +22,7 @@ · 4 unmodified lines
2222 "@cloudflare/vite-plugin": "^1.31.1",
2323 "@effect-atom/atom": "^0.5.0",
2424 "@effect-atom/atom-react": "^0.5.0",
25+ "@effect/opentelemetry": "^0.63.0",
2526 "@effect/platform": "catalog:",
2627 "@executor/api": "workspace:*",
2728 "@executor/env": "workspace:*",
@@ -36,6 +37,14 @@ · 8 unmodified lines
3637 "@executor/sdk": "workspace:*",
3738 "@executor/storage-postgres": "workspace:*",
3839 "@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",
3948 "@tanstack/react-router": "catalog:",
4049 "@tanstack/react-start": "catalog:",
4150 "@workos-inc/node": "^8.11.1",
apps/cloud/src/api.ts+62−5
@@ -3,6 +3,7 @@ · 2 unmodified lines
33 // ---------------------------------------------------------------------------
44
55 import { env } from "cloudflare:workers";
6+import * as Sentry from "@sentry/cloudflare";
67 import {
78 HttpApiBuilder,
89 HttpApiSwagger,
@@ -48,6 +49,7 @@ import { DbService } from "./services/db"; · 39 unmodified lines
4849 import { createOrgExecutor } from "./services/executor";
4950 import { TeamOrgApi } from "./team/compose";
5051 import { TeamHandlers } from "./team/handlers";
52+import { TelemetryLive } from "./services/telemetry";
5153 import { server } from "./env";
5254
5355 // ---------------------------------------------------------------------------
@@ -73,7 +75,7 @@ const SharedServices = Layer.mergeAll( · 19 unmodified lines
7375 UserStoreLive,
7476 WorkOSAuth.Default,
7577 HttpServer.layerContext,
76−);
78+).pipe(Layer.provideMerge(TelemetryLive));
7779 const ProtectedCloudApiLive = HttpApiBuilder.api(ProtectedCloudApi).pipe(
7880 Layer.provide(
7981 Layer.mergeAll(
@@ -249,6 +251,7 @@ const handleAutumnRequest = async (request: Request): Promise<Response> => { · 169 unmodified lines
249251
250252 return Effect.runPromise(program.pipe(Effect.provide(SharedServices), Effect.scoped)).catch(
251253 (err) => {
254+ Sentry.captureException(err);
252255 console.error("[autumn] request failed:", err instanceof Error ? err.stack : err);
253256 return Response.json({ error: "Internal server error" }, { status: 500 });
254257 },
@@ -259,9 +262,41 @@ const handleAutumnRequest = async (request: Request): Promise<Response> => { · 4 unmodified lines
259262 // Widget token endpoint — returns a WorkOS widget token for the session user
260263 // ---------------------------------------------------------------------------
261264
265+// ---------------------------------------------------------------------------
266+// Sentry tunnel — proxies client events to Sentry to bypass ad blockers
267+// ---------------------------------------------------------------------------
268+
269+const SENTRY_HOST = "o4511196985556992.ingest.us.sentry.io";
270+const SENTRY_PROJECT_IDS = new Set(["4511197001416704", "4511197010067456"]);
271+
272+const 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+
262293 export const handleApiRequest = async (request: Request): Promise<Response> => {
263294 const pathname = new URL(request.url).pathname;
264295
296+ if (pathname === "/sentry-tunnel" && request.method === "POST") {
297+ return handleSentryTunnel(request);
298+ }
299+
265300 if (isTeamPath(pathname)) {
266301 const handler = createTeamHandler();
267302 try {
@@ -293,6 +328,30 @@ export const handleApiRequest = async (request: Request): Promise<Response> => { · 25 unmodified lines
293328 const codeExecutor = makeDynamicWorkerExecutor({ loader: env.LOADER });
294329 const handler = yield* buildProtectedHandler(org.id, org.name, codeExecutor);
295330 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+
296355 return { response, orgId: org.id };
297356 });
298357
@@ -325,10 +384,8 @@ export const handleApiRequest = async (request: Request): Promise<Response> => { · 26 unmodified lines
325384
326385 return result.response;
327386 } catch (err) {
387+ Sentry.captureException(err);
328388 console.error("[api] request failed:", err instanceof Error ? err.stack : err);
329− return Response.json(
330− { error: err instanceof Error ? err.message : "Internal server error" },
331− { status: 500 },
332− );
389+ return Response.json({ error: "Internal server error" }, { status: 500 });
333390 }
334391 };
apps/cloud/src/env.ts+6−0
@@ -12,6 +12,9 @@ const serverShape = { · 11 unmodified lines
1212 WORKOS_COOKIE_PASSWORD: Env.string("WORKOS_COOKIE_PASSWORD"),
1313 VITE_PUBLIC_SITE_URL: Env.stringOr("VITE_PUBLIC_SITE_URL", ""),
1414 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"),
1518 };
1619
1720 type SharedEnv = Readonly<{
@@ -27,6 +30,9 @@ type ServerEnv = SharedEnv & · 9 unmodified lines
2730 WORKOS_COOKIE_PASSWORD: string;
2831 VITE_PUBLIC_SITE_URL: string;
2932 AUTUMN_SECRET_KEY: string;
33+ SENTRY_DSN: string;
34+ AXIOM_TOKEN: string;
35+ AXIOM_DATASET: string;
3036 }>;
3137
3238 type 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
66 import { Data, Effect, Layer } from "effect";
77 import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
88 import { WorkerTransport, type TransportState } from "agents/mcp";
9+import { drizzle } from "drizzle-orm/postgres-js";
10+import postgres from "postgres";
911
1012 import { createExecutorMcpServer } from "@executor/host-mcp";
1113 import { makeDynamicWorkerExecutor } from "@executor/runtime-dynamic-worker";
14+import type { DrizzleDb } from "@executor/storage-postgres";
15+import * as sharedSchema from "@executor/storage-postgres/schema";
1216
1317 import { UserStoreService } from "./auth/context";
1418 import { server } from "./env";
1519 import { createOrgExecutor } from "./services/executor";
1620 import { DbService } from "./services/db";
21+import * as cloudSchema from "./services/schema";
1722
1823 // ---------------------------------------------------------------------------
1924 // Types
@@ -23,47 +28,19 @@ export type McpSessionInit = { · 3 unmodified lines
2328 organizationId: string;
2429 };
2530
26−// Heartbeat interval — keeps the DO alive by re-scheduling an alarm before
27−// Cloudflare's ~60s idle eviction kicks in.
2831 const 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.
3232 const SESSION_TIMEOUT_MS = 5 * 60 * 1000;
3333
3434 // ---------------------------------------------------------------------------
35−// Session initialization effect
35+// Errors
3636 // ---------------------------------------------------------------------------
3737
38−const DbLive = DbService.Live;
39−const UserStoreLive = UserStoreService.Live.pipe(Layer.provide(DbLive));
40−const Services = Layer.mergeAll(DbLive, UserStoreLive);
41−
4238 class OrganizationNotFoundError extends Data.TaggedError("OrganizationNotFoundError")<{
4339 readonly organizationId: string;
4440 }> {}
4541
46−const 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−
6542 // ---------------------------------------------------------------------------
66−// JSON-RPC error response helper
43+// Helpers
6744 // ---------------------------------------------------------------------------
6845
6946 const jsonRpcError = (status: number, code: number, message: string) =>
@@ -72,6 +49,32 @@ const jsonRpcError = (status: number, code: number, message: string) => · 2 unmodified lines
7249 headers: { "content-type": "application/json" },
7350 });
7451
52+const 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+ */
63+const 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+
7578 // ---------------------------------------------------------------------------
7679 // Durable Object
7780 // ---------------------------------------------------------------------------
@@ -81,6 +84,7 @@ export class McpSessionDO extends DurableObject { · 3 unmodified lines
8184 private transport: WorkerTransport | null = null;
8285 private initialized = false;
8386 private lastActivityMs = 0;
87+ private dbHandle: { db: DrizzleDb; end: () => Promise<void> } | null = null;
8488
8589 private makeStorage() {
8690 return {
@@ -96,7 +100,25 @@ export class McpSessionDO extends DurableObject { · 9 unmodified lines
96100 async init(token: McpSessionInit): Promise<void> {
97101 if (this.initialized) return;
98102
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);
100122
101123 this.transport = new WorkerTransport({
102124 sessionIdGenerator: () => this.ctx.id.toString(),
@@ -143,6 +165,10 @@ export class McpSessionDO extends DurableObject { · 40 unmodified lines
143165 await this.mcpServer.close().catch(() => undefined);
144166 this.mcpServer = null;
145167 }
168+ if (this.dbHandle) {
169+ await this.dbHandle.end();
170+ this.dbHandle = null;
171+ }
146172 this.initialized = false;
147173 }
148174 }
apps/cloud/src/routes/__root.tsx+11−0
@@ -1,4 +1,5 @@
11 import React from "react";
2+import * as Sentry from "@sentry/react";
23 import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router";
34 import { AutumnProvider } from "autumn-js/react";
45 import { ExecutorProvider } from "@executor/react/api/provider";
@@ -8,6 +9,16 @@ import { LoginPage } from "../web/pages/login"; · 3 unmodified lines
89 import { Shell } from "../web/shell";
910 import appCss from "@executor/react/globals.css?url";
1011
12+if (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+
1122 export const Route = createRootRoute({
1223 head: () => ({
1324 meta: [
apps/cloud/src/server.ts+12−3
@@ -1,8 +1,17 @@
1+import * as Sentry from "@sentry/cloudflare";
12 import handler from "@tanstack/react-start/server-entry";
23
34 // Export Durable Objects as named exports
45 export { McpSessionDO } from "./mcp-session";
56
6−export default {
7− fetch: handler.fetch,
8−};
7+export default Sentry.withSentry(
8+ (env: Record<string, string>) => ({
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+
5+import { Layer } from "effect";
6+import { WebSdk, Tracer as OtelTracer } from "@effect/opentelemetry";
7+import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
8+import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
9+import { server } from "../env";
10+
11+const 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+ */
33+export 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
44 "compatibility_date": "2025-04-01",
55 "compatibility_flags": ["nodejs_compat"],
66 "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+ ],
813 "limits": {
914 "cpu_ms": 300000,
1015 },
@@ -44,6 +49,7 @@ · 33 unmodified lines
4449 },
4550 ],
4651 "vars": {
52+ "VITE_PUBLIC_SENTRY_DSN": "https://e20b1bdeea27008092a4dc0ac303e97a@o4511196985556992.ingest.us.sentry.io/4511197010067456",
4753 "VITE_PUBLIC_SITE_URL": "https://executor.sh",
4854 },
4955 }
bun.lock+85−0
@@ -48,6 +48,7 @@ · 47 unmodified lines
4848 "@cloudflare/vite-plugin": "^1.31.1",
4949 "@effect-atom/atom": "^0.5.0",
5050 "@effect-atom/atom-react": "^0.5.0",
51+ "@effect/opentelemetry": "^0.63.0",
5152 "@effect/platform": "catalog:",
5253 "@executor/api": "workspace:*",
5354 "@executor/env": "workspace:*",
@@ -62,6 +63,14 @@ · 8 unmodified lines
6263 "@executor/sdk": "workspace:*",
6364 "@executor/storage-postgres": "workspace:*",
6465 "@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",
6574 "@tanstack/react-router": "catalog:",
6675 "@tanstack/react-start": "catalog:",
6776 "@workos-inc/node": "^8.11.1",
@@ -885,6 +894,8 @@ · 817 unmodified lines
885894
886895 "@effect/language-service": ["@effect/language-service@0.84.3", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-zpxi6rLCwst/cBQd7ElwDvt36Y6Jvz8v6bCLnNiOL6OXvdLmqjOFWyzWZdMh92vvBQA/aVKhfIAAOP3o4wKt0A=="],
887896
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+
888899 "@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=="],
889900
890901 "@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
12151226
12161227 "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
12171228
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+
12181255 "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="],
12191256
12201257 "@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="],
@@ -1413,6 +1450,26 @@ · 192 unmodified lines
14131450
14141451 "@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="],
14151452
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+
14161473 "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
14171474
14181475 "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
@@ -1637,6 +1694,22 @@ · 218 unmodified lines
16371694
16381695 "@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=="],
16391696
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+
16401713 "@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=="],
16411714
16421715 "@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
28412914
28422915 "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="],
28432916
2917+ "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
2918+
28442919 "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
28452920
28462921 "lookpath": ["lookpath@1.2.3", "", { "bin": { "lookpath": "bin/lookpath.js" } }, "sha512-kthRVhf4kH4+HW3anM4UBHxsw/XFESf13euCEldhXr6GpBdmBoa7rDd7WO5G0Mhd4G5XtKTcEy8OR0iRZXpS3Q=="],
@@ -3251,6 +3326,8 @@ · 404 unmodified lines
32513326
32523327 "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
32533328
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+
32543331 "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=="],
32553332
32563333 "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
39053982
39063983 "@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
39073984
3985+ "@opentelemetry/api-logs/@opentelemetry/api": ["@opentelemetry/api@1.9.1", "", {}, "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q=="],
3986+
39083987 "@poppinss/colors/kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
39093988
39103989 "@poppinss/dumper/@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="],
@@ -4001,6 +4080,8 @@ · 90 unmodified lines
40014080
40024081 "@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=="],
40034082
4083+ "@sentry/cloudflare/@opentelemetry/api": ["@opentelemetry/api@1.9.1", "", {}, "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q=="],
4084+
40044085 "@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=="],
40054086
40064087 "@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
41754256
41764257 "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
41774258
4259+ "protobufjs/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="],
4260+
41784261 "public-encrypt/bn.js": ["bn.js@4.12.3", "", {}, "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g=="],
41794262
41804263 "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
45554638
45564639 "pkg-dir/find-up/locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
45574640
4641+ "protobufjs/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
4642+
45584643 "read-yaml-file/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
45594644
45604645 "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 @@
1−import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
1+import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
22
33 const ALGORITHM = "aes-256-gcm";
44 const IV_LENGTH = 12;
@@ -9,7 +9,6 @@ const AUTH_TAG_LENGTH = 16; · 4 unmodified lines
99 * Uses SHA-256 to normalize any length input to exactly 32 bytes.
1010 */
1111 const deriveKey = (key: string): Buffer => {
12− const { createHash } = require("node:crypto") as typeof import("node:crypto");
1312 return createHash("sha256").update(key).digest();
1413 };
1514

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