diff --git a/apps/web/src/components/video-generator.tsx b/apps/web/src/components/video-generator.tsx
index e162488d9..7bda31797 100644
--- a/apps/web/src/components/video-generator.tsx
+++ b/apps/web/src/components/video-generator.tsx
@@ -181,6 +181,10 @@ export default function VideoGenerator({ className = '' }: VideoGeneratorProps)
+<<<<<<< HEAD
+=======
+ {!prompt.trim() && (
+
+ Enter a prompt to enable video generation.
+
+ )}
+>>>>>>> origin/main
{/* Warning */}
diff --git a/apps/web/src/lib/__tests__/error-handling-stack-safety.test.ts b/apps/web/src/lib/__tests__/error-handling-stack-safety.test.ts
new file mode 100644
index 000000000..469411fc1
--- /dev/null
+++ b/apps/web/src/lib/__tests__/error-handling-stack-safety.test.ts
@@ -0,0 +1,56 @@
+import { describe, expect, it } from 'vitest';
+import { formatApiError } from '@/lib/error-handling';
+
+/**
+ * Security regression coverage for #945 / PR #942.
+ *
+ * `formatApiError` must never surface stack-derived implementation details in
+ * the client-visible error payload. These tests pin that boundary so the
+ * general web suite cannot pass while a regression re-exposes `Error.stack`.
+ */
+describe('formatApiError stack-trace safety', () => {
+ const STACK_MARKER = 'SECRET_STACK_FRAME at /srv/app/internal/secret.ts:42:13';
+
+ it('returns only the public message for an Error and never leaks the stack', () => {
+ const error = new Error('Something failed publicly');
+ error.stack = `Error: Something failed publicly\n ${STACK_MARKER}`;
+
+ const result = formatApiError(error);
+
+ expect(result).toEqual({ message: 'Something failed publicly' });
+ // The serialized payload is what reaches the client — assert the whole
+ // shape is free of any stack-derived detail, not just the known keys.
+ expect(JSON.stringify(result)).not.toContain(STACK_MARKER);
+ expect(JSON.stringify(result)).not.toContain('secret.ts');
+ expect(result).not.toHaveProperty('stack');
+ expect(result.details).toBeUndefined();
+ });
+
+ it('falls back to the default message when an Error has an empty message', () => {
+ const error = new Error('');
+ error.stack = `Error\n ${STACK_MARKER}`;
+
+ const result = formatApiError(error, 'An error occurred');
+
+ expect(result).toEqual({ message: 'An error occurred' });
+ expect(JSON.stringify(result)).not.toContain(STACK_MARKER);
+ });
+
+ it('formats the non-Error object shape without exposing extra internals', () => {
+ const result = formatApiError({
+ message: 'Upstream rejected',
+ code: 'E_UPSTREAM',
+ stack: STACK_MARKER,
+ });
+
+ expect(result).toEqual({ message: 'Upstream rejected', code: 'E_UPSTREAM' });
+ expect(JSON.stringify(result)).not.toContain(STACK_MARKER);
+ expect(result).not.toHaveProperty('stack');
+ expect(result.details).toBeUndefined();
+ });
+
+ it('handles primitive errors with only the public string or default', () => {
+ expect(formatApiError('plain failure')).toEqual({ message: 'plain failure' });
+ expect(formatApiError('', 'fallback message')).toEqual({ message: 'fallback message' });
+ });
+});
diff --git a/apps/web/src/lib/__tests__/video-generator-accessibility.test.ts b/apps/web/src/lib/__tests__/video-generator-accessibility.test.ts
new file mode 100644
index 000000000..008a6d90e
--- /dev/null
+++ b/apps/web/src/lib/__tests__/video-generator-accessibility.test.ts
@@ -0,0 +1,49 @@
+import { readFileSync } from 'node:fs';
+import { fileURLToPath } from 'node:url';
+import { dirname, join } from 'node:path';
+import { describe, expect, it } from 'vitest';
+
+const webSrc = join(dirname(fileURLToPath(import.meta.url)), '../..');
+
+function readSource(relativePath: string) {
+ return readFileSync(join(webSrc, relativePath), 'utf8');
+}
+
+// Static-source coverage for the video-generator disabled-state accessibility
+// contract (see components/dashboard-search-accessibility.test.ts for the same
+// pattern). The web suite runs in the `node` environment with no jsdom, so the
+// button's rendered state is asserted from the source expressions that derive
+// it rather than by mounting the component.
+describe('video generator disabled-state accessibility', () => {
+ const source = readSource('components/video-generator.tsx');
+
+ const generateButton = source.match(/
-=======
- const rawParam = params?.callbackUrl;
- const raw = Array.isArray(rawParam) ? rawParam[0] : rawParam;
- const callbackUrl = safeCallbackPath(raw ?? '/dashboard');
-
- return (
-