mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix: error-only Sentry telemetry, storm-proof capture, and crash fixes (#476)
Removes Sentry tracing entirely (BullMQ idle polling burned 4.8M transactions in 2 days at the baked 0.1 rate), decouples PostHog sampling, and replaces the type-only error scrub with a vetted-field sanitizer plus SafeError/ToolInputError contracts. One classified capture path with per-signature throttles and a per-process ceiling makes storms impossible (NODE-1E was 4,541 events from one 30s loop). Browser errors move to a dedicated web Sentry project with their own source maps. Adds the SNAPOTTER_TELEMETRY runtime kill switch and silences test fleets. Crash fixes: remote 204/304 SSRF process kill (NODE-20), conversion-preset boot crash loop (NODE-21), Redis version preflight + unhandled subscribe rejection (NODE-1T), Sign PDF on plain-http origins (NODE-1K/1M), wavesurfer/pdf.js teardown rejections (NODE-1P/1N), bundle-import ZlibError to 400 (NODE-1Z), chart-maker input errors declassified (NODE-1H/1J), asset requests skip the session DB lookup (NODE-1D).
This commit is contained in:
@@ -5,6 +5,7 @@ import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "re
|
||||
import { useTranslation } from "@/contexts/i18n-context";
|
||||
import { toNormalizedRect } from "@/lib/sign-geometry";
|
||||
import type { SavedSignature } from "@/lib/signature-store";
|
||||
import { safeRandomUUID } from "@/lib/uuid";
|
||||
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
|
||||
"pdfjs-dist/build/pdf.worker.min.mjs",
|
||||
@@ -90,7 +91,11 @@ export const SignCanvas = forwardRef<SignCanvasRef, Props>(function SignCanvas(
|
||||
setPageCount(doc.numPages);
|
||||
setPage(0);
|
||||
setDocReady(true);
|
||||
})();
|
||||
})().catch(() => {
|
||||
// loadingTask.destroy() in the cleanup rejects the in-flight promise;
|
||||
// swallowing it is the fix for Sentry NODE-1N. A genuine load failure
|
||||
// leaves docReady false, which the existing UI already handles.
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
docRef.current?.loadingTask.destroy();
|
||||
@@ -181,7 +186,10 @@ export const SignCanvas = forwardRef<SignCanvasRef, Props>(function SignCanvas(
|
||||
}
|
||||
layer.batchDraw();
|
||||
onSelectionChange?.(false);
|
||||
})();
|
||||
})().catch(() => {
|
||||
// getPage()/render() reject when the loadingTask is destroyed mid-render
|
||||
// (file swap or unmount); expected teardown, same as the load effect.
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
@@ -241,7 +249,7 @@ export const SignCanvas = forwardRef<SignCanvasRef, Props>(function SignCanvas(
|
||||
layer.add(node);
|
||||
tr.nodes([node]);
|
||||
layer.batchDraw();
|
||||
placementsRef.current.push({ id: crypto.randomUUID(), page, node });
|
||||
placementsRef.current.push({ id: safeRandomUUID(), page, node });
|
||||
onSelectionChange?.(true);
|
||||
emitCount();
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
type SavedSignature,
|
||||
} from "@/lib/signature-store";
|
||||
import { generateId } from "@/lib/utils";
|
||||
import { safeRandomUUID } from "@/lib/uuid";
|
||||
import { useFileStore } from "@/stores/file-store";
|
||||
import type { SignCanvasRef } from "./sign-canvas";
|
||||
import { SignaturePad } from "./signature-pad";
|
||||
@@ -126,7 +127,7 @@ export function SignPdfSettings({ signProps }: { signProps?: SignProps }) {
|
||||
const handleSavePad = (dataUrl: string, remember: boolean) => {
|
||||
const sig: SavedSignature = remember
|
||||
? addSignature(dataUrl)
|
||||
: { id: crypto.randomUUID(), dataUrl, createdAt: Date.now() };
|
||||
: { id: safeRandomUUID(), dataUrl, createdAt: Date.now() };
|
||||
if (remember) refresh();
|
||||
signProps?.canvasRef.current?.addSignature(sig);
|
||||
setPadOpen(false);
|
||||
|
||||
Reference in New Issue
Block a user