= ({ rawMessage, children, fallback }) => {
+ const validation = validateSharedMessage(rawMessage);
+
+ if (!validation.isValid || !validation.data) {
+ return (
+ <>{fallback || [Unsafe or Malformed Message Ignored]
}>
+ );
+ }
+
+ const safeBody = sanitizeMessageBody(validation.data.body);
+
+ return (
+ <>
+ {children({
+ sender: validation.data.sender,
+ subject: validation.data.subject,
+ body: safeBody,
+ timestamp: validation.data.timestamp,
+ })}
+ >
+ );
+};
diff --git a/tools/v1/team/shared-team-inbox/hooks/useSharedInboxSafety.ts b/tools/v1/team/shared-team-inbox/hooks/useSharedInboxSafety.ts
new file mode 100644
index 000000000..48608595a
--- /dev/null
+++ b/tools/v1/team/shared-team-inbox/hooks/useSharedInboxSafety.ts
@@ -0,0 +1,44 @@
+import { useMemo } from 'react';
+import { validateSharedMessage, ValidatedSharedMessage } from '../utils/validation';
+import { sanitizeMessageBody } from '../utils/sanitization';
+import { paginateInboxMessages, truncateLargeBody, PaginatedResult } from '../utils/performance';
+
+export interface UseSharedInboxSafetyOptions {
+ rawMessages: unknown[];
+ page?: number;
+ pageSize?: number;
+}
+
+export function useSharedInboxSafety({ rawMessages, page = 1, pageSize = 50 }: UseSharedInboxSafetyOptions) {
+ return useMemo(() => {
+ const validMessages: ValidatedSharedMessage[] = [];
+ const rejectedCount = { value: 0 };
+
+ if (Array.isArray(rawMessages)) {
+ for (const raw of rawMessages) {
+ const validation = validateSharedMessage(raw);
+ if (validation.isValid && validation.data) {
+ const sanitizedBody = sanitizeMessageBody(validation.data.body);
+ const { text: truncatedBody } = truncateLargeBody(sanitizedBody);
+
+ validMessages.push({
+ ...validation.data,
+ body: truncatedBody,
+ });
+ } else {
+ rejectedCount.value += 1;
+ }
+ }
+ }
+
+ const paginated: PaginatedResult = paginateInboxMessages(validMessages, page, pageSize);
+
+ return {
+ messages: paginated.items,
+ hasMore: paginated.hasMore,
+ totalCount: paginated.totalCount,
+ rejectedCount: rejectedCount.value,
+ page: paginated.page,
+ };
+ }, [rawMessages, page, pageSize]);
+}
diff --git a/tools/v1/team/shared-team-inbox/utils/performance.ts b/tools/v1/team/shared-team-inbox/utils/performance.ts
new file mode 100644
index 000000000..09a43c9eb
--- /dev/null
+++ b/tools/v1/team/shared-team-inbox/utils/performance.ts
@@ -0,0 +1,49 @@
+import { ValidatedSharedMessage } from './validation';
+
+const DEFAULT_PAGE_SIZE = 50;
+const PREVIEW_CHAR_LIMIT = 100000; // 100KB character threshold
+
+export interface PaginatedResult {
+ items: T[];
+ hasMore: boolean;
+ totalCount: number;
+ page: number;
+}
+
+/**
+ * Enforces strict pagination boundaries on large inbox datasets.
+ */
+export function paginateInboxMessages(
+ messages: ValidatedSharedMessage[],
+ page: number = 1,
+ pageSize: number = DEFAULT_PAGE_SIZE
+): PaginatedResult {
+ const safePage = Math.max(1, page);
+ const safePageSize = Math.min(Math.max(1, pageSize), DEFAULT_PAGE_SIZE);
+
+ const startIndex = (safePage - 1) * safePageSize;
+ const endIndex = startIndex + safePageSize;
+
+ const slicedItems = messages.slice(startIndex, endIndex);
+
+ return {
+ items: slicedItems,
+ hasMore: endIndex < messages.length,
+ totalCount: messages.length,
+ page: safePage,
+ };
+}
+
+/**
+ * Truncates oversized message body texts to prevent main thread rendering lockups.
+ */
+export function truncateLargeBody(body: string, limit: number = PREVIEW_CHAR_LIMIT): { text: string; isTruncated: boolean } {
+ if (body.length <= limit) {
+ return { text: body, isTruncated: false };
+ }
+
+ return {
+ text: body.slice(0, limit) + '\n\n[Content truncated for performance size limit]',
+ isTruncated: true,
+ };
+}
diff --git a/tools/v1/team/shared-team-inbox/utils/sanitization.ts b/tools/v1/team/shared-team-inbox/utils/sanitization.ts
new file mode 100644
index 000000000..ae8942951
--- /dev/null
+++ b/tools/v1/team/shared-team-inbox/utils/sanitization.ts
@@ -0,0 +1,22 @@
+const DANGEROUS_TAGS_REGEX = /