From 21ce202110644aac87d5b1d40f36de40ed2411cd Mon Sep 17 00:00:00 2001 From: Bhekani Khumalo Date: Wed, 10 Jun 2026 18:38:10 +0100 Subject: [PATCH] refactor(web): guard RightRail attachment payload instead of casting The attachments rail branch cast each payload item straight to AttachmentView (`item as AttachmentView`) with no runtime check, so a malformed payload would flow garbage into AttachmentActions. Filter the array through an isAttachmentView guard so only well-formed attachments render. (The sender-profile and commitments panels already validate their payloads internally via extractSenderProfile / extractCommitments, so they are not a crash risk despite taking `unknown`.) --- apps/web/src/components/RightRail.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/apps/web/src/components/RightRail.tsx b/apps/web/src/components/RightRail.tsx index 6cdc1436..17bdc37e 100644 --- a/apps/web/src/components/RightRail.tsx +++ b/apps/web/src/components/RightRail.tsx @@ -93,12 +93,12 @@ function RailContent({ kind, payload }: { kind: string; payload: unknown }) { ); } if (kind === "attachments" && Array.isArray(payload)) { + const attachments = payload.filter(isAttachmentView); return (
- {payload.map((item, index) => { - const attachment = item as AttachmentView; - return ; - })} + {attachments.map((attachment, index) => ( + + ))}
); } @@ -143,9 +143,7 @@ interface RoutePickerPayload { function isRoutePickerPayload(value: unknown): value is RoutePickerPayload { return ( - isRecord(value) && - Array.isArray(value.messageIds) && - typeof value.fromQueueLabel === "string" + isRecord(value) && Array.isArray(value.messageIds) && typeof value.fromQueueLabel === "string" ); } @@ -598,6 +596,12 @@ function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null; } +function isAttachmentView(value: unknown): value is AttachmentView { + return ( + isRecord(value) && typeof value.filename === "string" && typeof value.mime_type === "string" + ); +} + function formatNumber(value: number): string { return new Intl.NumberFormat(undefined, { maximumFractionDigits: 0 }).format(value); }