diff --git a/web/avatars/edit-thread-avatar-menu.react.js b/web/avatars/edit-thread-avatar-menu.react.js
--- a/web/avatars/edit-thread-avatar-menu.react.js
+++ b/web/avatars/edit-thread-avatar-menu.react.js
@@ -6,11 +6,7 @@
 import { EditThreadAvatarContext } from 'lib/components/base-edit-thread-avatar-provider.react.js';
 import { useModalContext } from 'lib/components/modal-provider.react.js';
 import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type {
-  RawThreadInfo,
-  LegacyThreadInfo,
-} from 'lib/types/thread-types.js';
+import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js';
 
 import { useUploadAvatarMedia } from './avatar-hooks.react.js';
 import css from './edit-avatar-menu.css';
@@ -26,7 +22,7 @@
 );
 
 type Props = {
-  +threadInfo: RawThreadInfo | LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: RawThreadInfo | ThreadInfo,
 };
 function EditThreadAvatarMenu(props: Props): React.Node {
   const { threadInfo } = props;
diff --git a/web/avatars/edit-thread-avatar.react.js b/web/avatars/edit-thread-avatar.react.js
--- a/web/avatars/edit-thread-avatar.react.js
+++ b/web/avatars/edit-thread-avatar.react.js
@@ -5,19 +5,15 @@
 
 import { EditThreadAvatarContext } from 'lib/components/base-edit-thread-avatar-provider.react.js';
 import { threadHasPermission } from 'lib/shared/thread-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadPermissions } from 'lib/types/thread-permission-types.js';
-import type {
-  RawThreadInfo,
-  LegacyThreadInfo,
-} from 'lib/types/thread-types.js';
+import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js';
 
 import EditThreadAvatarMenu from './edit-thread-avatar-menu.react.js';
 import css from './edit-thread-avatar.css';
 import ThreadAvatar from './thread-avatar.react.js';
 
 type Props = {
-  +threadInfo: RawThreadInfo | LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: RawThreadInfo | ThreadInfo,
   +disabled?: boolean,
 };
 function EditThreadAvatar(props: Props): React.Node {
diff --git a/web/avatars/thread-avatar.react.js b/web/avatars/thread-avatar.react.js
--- a/web/avatars/thread-avatar.react.js
+++ b/web/avatars/thread-avatar.react.js
@@ -8,18 +8,14 @@
 } from 'lib/shared/avatar-utils.js';
 import { getSingleOtherUser } from 'lib/shared/thread-utils.js';
 import type { AvatarSize } from 'lib/types/avatar-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadTypes } from 'lib/types/thread-types-enum.js';
-import type {
-  LegacyThreadInfo,
-  RawThreadInfo,
-} from 'lib/types/thread-types.js';
+import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js';
 
 import Avatar from './avatar.react.js';
 import { useSelector } from '../redux/redux-utils.js';
 
 type Props = {
-  +threadInfo: RawThreadInfo | LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: RawThreadInfo | ThreadInfo,
   +size: AvatarSize,
   +showSpinner?: boolean,
 };
diff --git a/web/avatars/thread-emoji-avatar-selection-modal.react.js b/web/avatars/thread-emoji-avatar-selection-modal.react.js
--- a/web/avatars/thread-emoji-avatar-selection-modal.react.js
+++ b/web/avatars/thread-emoji-avatar-selection-modal.react.js
@@ -12,16 +12,12 @@
   ClientAvatar,
   ClientEmojiAvatar,
 } from 'lib/types/avatar-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type {
-  RawThreadInfo,
-  LegacyThreadInfo,
-} from 'lib/types/thread-types.js';
+import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js';
 
 import EmojiAvatarSelectionModal from './emoji-avatar-selection-modal.react.js';
 
 type Props = {
-  +threadInfo: LegacyThreadInfo | RawThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: RawThreadInfo | ThreadInfo,
 };
 
 function ThreadEmojiAvatarSelectionModal(props: Props): React.Node {
diff --git a/web/calendar/day.react.js b/web/calendar/day.react.js
--- a/web/calendar/day.react.js
+++ b/web/calendar/day.react.js
@@ -16,9 +16,8 @@
 import { onScreenThreadInfos as onScreenThreadInfosSelector } from 'lib/selectors/thread-selectors.js';
 import { entryKey } from 'lib/shared/entry-utils.js';
 import type { EntryInfo } from 'lib/types/entry-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import type { Dispatch } from 'lib/types/redux-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { dateString, dateFromString } from 'lib/utils/date-utils.js';
 import { useDispatch } from 'lib/utils/redux-utils.js';
 
@@ -39,9 +38,7 @@
 };
 type Props = {
   ...BaseProps,
-  +onScreenThreadInfos: $ReadOnlyArray<
-    LegacyThreadInfo | MinimallyEncodedThreadInfo,
-  >,
+  +onScreenThreadInfos: $ReadOnlyArray<ThreadInfo>,
   +viewerID: ?string,
   +loggedIn: boolean,
   +nextLocalID: number,
diff --git a/web/chat/chat-input-bar.react.js b/web/chat/chat-input-bar.react.js
--- a/web/chat/chat-input-bar.react.js
+++ b/web/chat/chat-input-bar.react.js
@@ -36,12 +36,12 @@
 import type { CalendarQuery } from 'lib/types/entry-types.js';
 import type { LoadingStatus } from 'lib/types/loading-types.js';
 import { messageTypes } from 'lib/types/message-types-enum.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadPermissions } from 'lib/types/thread-permission-types.js';
 import {
   type LegacyThreadInfo,
   type ClientThreadJoinRequest,
   type ThreadJoinPayload,
+  type ThreadInfo,
 } from 'lib/types/thread-types.js';
 import { type UserInfos } from 'lib/types/user-types.js';
 import {
@@ -68,7 +68,7 @@
 } from '../utils/typeahead-utils.js';
 
 type BaseProps = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +inputState: InputState,
 };
 type Props = {
diff --git a/web/chat/chat-message-list.react.js b/web/chat/chat-message-list.react.js
--- a/web/chat/chat-message-list.react.js
+++ b/web/chat/chat-message-list.react.js
@@ -26,9 +26,8 @@
 import { messageKey } from 'lib/shared/message-utils.js';
 import { threadIsPending } from 'lib/shared/thread-utils.js';
 import type { FetchMessageInfosPayload } from 'lib/types/message-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadTypes } from 'lib/types/thread-types-enum.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import {
   type DispatchActionPromise,
   useDispatchActionPromise,
@@ -56,7 +55,7 @@
 const editBoxTopMargin = 10;
 
 type BaseProps = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 type Props = {
diff --git a/web/chat/chat-thread-list-item-menu.react.js b/web/chat/chat-thread-list-item-menu.react.js
--- a/web/chat/chat-thread-list-item-menu.react.js
+++ b/web/chat/chat-thread-list-item-menu.react.js
@@ -5,15 +5,14 @@
 
 import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
 import useToggleUnreadStatus from 'lib/hooks/toggle-unread-status.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import css from './chat-thread-list-item-menu.css';
 import Button from '../components/button.react.js';
 import { useThreadIsActive } from '../selectors/thread-selectors.js';
 
 type Props = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +mostRecentNonLocalMessage: ?string,
   +renderStyle?: 'chat' | 'thread',
 };
diff --git a/web/chat/chat-thread-list-see-more-sidebars.react.js b/web/chat/chat-thread-list-see-more-sidebars.react.js
--- a/web/chat/chat-thread-list-see-more-sidebars.react.js
+++ b/web/chat/chat-thread-list-see-more-sidebars.react.js
@@ -5,14 +5,13 @@
 import { IoIosMore } from 'react-icons/io/index.js';
 
 import { useModalContext } from 'lib/components/modal-provider.react.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import css from './chat-thread-list.css';
 import SidebarsModal from '../modals/threads/sidebars/sidebars-modal.react.js';
 
 type Props = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +unread: boolean,
 };
 function ChatThreadListSeeMoreSidebars(props: Props): React.Node {
diff --git a/web/chat/composed-message.react.js b/web/chat/composed-message.react.js
--- a/web/chat/composed-message.react.js
+++ b/web/chat/composed-message.react.js
@@ -12,8 +12,7 @@
 import { type ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
 import { getMessageLabel } from 'lib/shared/edit-messages-utils.js';
 import { assertComposableMessageType } from 'lib/types/message-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import { type ThreadInfo } from 'lib/types/thread-types.js';
 
 import { getComposedMessageID } from './chat-constants.js';
 import css from './chat-message-list.css';
@@ -51,7 +50,7 @@
 
 type BaseProps = {
   +item: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +shouldDisplayPinIndicator: boolean,
   +sendFailed: boolean,
   +children: React.Node,
diff --git a/web/chat/edit-message-provider.js b/web/chat/edit-message-provider.js
--- a/web/chat/edit-message-provider.js
+++ b/web/chat/edit-message-provider.js
@@ -5,8 +5,7 @@
 
 import ModalOverlay from 'lib/components/modal-overlay.react.js';
 import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types';
+import type { ThreadInfo } from 'lib/types/thread-types';
 
 import { EditTextMessage } from './edit-text-message.react.js';
 
@@ -19,7 +18,7 @@
 
 export type EditState = {
   +messageInfo: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +editedMessageDraft: ?string,
   +isError: boolean,
   +position?: ModalPosition,
diff --git a/web/chat/edit-text-message.react.js b/web/chat/edit-text-message.react.js
--- a/web/chat/edit-text-message.react.js
+++ b/web/chat/edit-text-message.react.js
@@ -8,8 +8,7 @@
 import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
 import { useEditMessage } from 'lib/shared/edit-messages-utils.js';
 import { trimMessage } from 'lib/shared/message-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import { type ThreadInfo } from 'lib/types/thread-types.js';
 
 import { editBoxBottomRowHeight } from './chat-constants.js';
 import ChatInputTextArea from './chat-input-text-area.react.js';
@@ -21,7 +20,7 @@
 
 type Props = {
   +item: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +background: boolean,
 };
 
diff --git a/web/chat/failed-send.react.js b/web/chat/failed-send.react.js
--- a/web/chat/failed-send.react.js
+++ b/web/chat/failed-send.react.js
@@ -11,8 +11,7 @@
   type RawComposableMessageInfo,
   assertComposableMessageType,
 } from 'lib/types/message-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { LegacyThreadInfo, ThreadInfo } from 'lib/types/thread-types.js';
 
 import css from './chat-message-list.css';
 import multimediaMessageSendFailed from './multimedia-message-send-failed.js';
@@ -23,7 +22,7 @@
 
 type BaseProps = {
   +item: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 type Props = {
   ...BaseProps,
diff --git a/web/chat/inline-engagement.react.js b/web/chat/inline-engagement.react.js
--- a/web/chat/inline-engagement.react.js
+++ b/web/chat/inline-engagement.react.js
@@ -7,8 +7,7 @@
 import type { ReactionInfo } from 'lib/selectors/chat-selectors.js';
 import { getInlineEngagementSidebarText } from 'lib/shared/inline-engagement-utils.js';
 import type { MessageInfo } from 'lib/types/message-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import css from './inline-engagement.css';
 import ReactionPill from './reaction-pill.react.js';
@@ -17,8 +16,8 @@
 
 type Props = {
   +messageInfo: MessageInfo,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
-  +sidebarThreadInfo: ?LegacyThreadInfo | ?MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
+  +sidebarThreadInfo: ?ThreadInfo,
   +reactions: ReactionInfo,
   +positioning: 'left' | 'center' | 'right',
   +label?: ?string,
diff --git a/web/chat/message-tooltip.react.js b/web/chat/message-tooltip.react.js
--- a/web/chat/message-tooltip.react.js
+++ b/web/chat/message-tooltip.react.js
@@ -7,8 +7,7 @@
 
 import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
 import { useNextLocalID } from 'lib/shared/message-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import {
   tooltipButtonStyle,
@@ -33,7 +32,7 @@
   +tooltipPositionStyle: TooltipPositionStyle,
   +tooltipSize: TooltipSize,
   +item: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 function MessageTooltip(props: MessageTooltipProps): React.Node {
   const {
diff --git a/web/chat/message.react.js b/web/chat/message.react.js
--- a/web/chat/message.react.js
+++ b/web/chat/message.react.js
@@ -5,8 +5,7 @@
 
 import { type ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
 import { messageTypes } from 'lib/types/message-types-enum.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import { type ThreadInfo } from 'lib/types/thread-types.js';
 import { longAbsoluteDate } from 'lib/utils/date-utils.js';
 
 import css from './chat-message-list.css';
@@ -18,7 +17,7 @@
 
 type Props = {
   +item: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +shouldDisplayPinIndicator: boolean,
 };
 function Message(props: Props): React.Node {
diff --git a/web/chat/multimedia-message.react.js b/web/chat/multimedia-message.react.js
--- a/web/chat/multimedia-message.react.js
+++ b/web/chat/multimedia-message.react.js
@@ -9,8 +9,7 @@
 } from 'lib/media/media-utils.js';
 import { type ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
 import { messageTypes } from 'lib/types/message-types-enum.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import { type ThreadInfo } from 'lib/types/thread-types.js';
 
 import css from './chat-message-list.css';
 import ComposedMessage from './composed-message.react.js';
@@ -19,7 +18,7 @@
 import Multimedia from '../media/multimedia.react.js';
 type BaseProps = {
   +item: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +shouldDisplayPinIndicator: boolean,
 };
 type Props = {
diff --git a/web/chat/relationship-prompt/relationship-prompt.js b/web/chat/relationship-prompt/relationship-prompt.js
--- a/web/chat/relationship-prompt/relationship-prompt.js
+++ b/web/chat/relationship-prompt/relationship-prompt.js
@@ -9,15 +9,14 @@
 import * as React from 'react';
 
 import { useRelationshipPrompt } from 'lib/hooks/relationship-prompt.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { userRelationshipStatus } from 'lib/types/relationship-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import RelationshipPromptButtonContainer from './relationship-prompt-button-container.js';
 import RelationshipPromptButton from './relationship-prompt-button.js';
 import { buttonThemes } from '../../components/button.react.js';
 
-type Props = { +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo };
+type Props = { +threadInfo: ThreadInfo };
 
 function RelationshipPrompt(props: Props) {
   const { threadInfo } = props;
diff --git a/web/chat/robotext-message.react.js b/web/chat/robotext-message.react.js
--- a/web/chat/robotext-message.react.js
+++ b/web/chat/robotext-message.react.js
@@ -5,9 +5,8 @@
 
 import { type RobotextChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
 import { threadInfoSelector } from 'lib/selectors/thread-selectors.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import type { Dispatch } from 'lib/types/redux-types.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import { type ThreadInfo } from 'lib/types/thread-types.js';
 import {
   entityTextToReact,
   useENSNamesForEntityText,
@@ -35,7 +34,7 @@
 
 type Props = {
   +item: RobotextChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 function RobotextMessage(props: Props): React.Node {
   let inlineEngagement;
@@ -105,7 +104,7 @@
 };
 type InnerThreadEntityProps = {
   ...BaseInnerThreadEntityProps,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +dispatch: Dispatch,
 };
 class InnerThreadEntity extends React.PureComponent<InnerThreadEntityProps> {
diff --git a/web/chat/text-message.react.js b/web/chat/text-message.react.js
--- a/web/chat/text-message.react.js
+++ b/web/chat/text-message.react.js
@@ -8,8 +8,7 @@
 import { colorIsDark } from 'lib/shared/color-utils.js';
 import { onlyEmojiRegex } from 'lib/shared/emojis.js';
 import { messageTypes } from 'lib/types/message-types-enum.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import { type ThreadInfo } from 'lib/types/thread-types.js';
 
 import css from './chat-message-list.css';
 import ComposedMessage from './composed-message.react.js';
@@ -19,7 +18,7 @@
 
 type Props = {
   +item: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +shouldDisplayPinIndicator: boolean,
 };
 function TextMessage(props: Props): React.Node {
diff --git a/web/chat/thread-menu.react.js b/web/chat/thread-menu.react.js
--- a/web/chat/thread-menu.react.js
+++ b/web/chat/thread-menu.react.js
@@ -15,10 +15,9 @@
   viewerIsMember,
   threadIsChannel,
 } from 'lib/shared/thread-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadPermissions } from 'lib/types/thread-permission-types.js';
 import { threadTypes } from 'lib/types/thread-types-enum.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import { type ThreadInfo } from 'lib/types/thread-types.js';
 import { useDispatchActionPromise } from 'lib/utils/action-utils.js';
 
 import css from './thread-menu.css';
@@ -36,7 +35,7 @@
 import { useSelector } from '../redux/redux-utils.js';
 
 type ThreadMenuProps = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function ThreadMenu(props: ThreadMenuProps): React.Node {
diff --git a/web/chat/thread-top-bar.react.js b/web/chat/thread-top-bar.react.js
--- a/web/chat/thread-top-bar.react.js
+++ b/web/chat/thread-top-bar.react.js
@@ -6,8 +6,7 @@
 import { useModalContext } from 'lib/components/modal-provider.react.js';
 import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
 import { threadIsPending } from 'lib/shared/thread-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js';
 
 import ThreadMenu from './thread-menu.react.js';
@@ -19,7 +18,7 @@
 import MessageSearchModal from '../modals/search/message-search-modal.react.js';
 
 type ThreadTopBarProps = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 function ThreadTopBar(props: ThreadTopBarProps): React.Node {
   const { threadInfo } = props;
diff --git a/web/components/message-result.react.js b/web/components/message-result.react.js
--- a/web/components/message-result.react.js
+++ b/web/components/message-result.react.js
@@ -6,8 +6,7 @@
 import { useThreadChatMentionCandidates } from 'lib/hooks/chat-mention-hooks.js';
 import { useStringForUser } from 'lib/hooks/ens-cache.js';
 import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { longAbsoluteDate } from 'lib/utils/date-utils.js';
 
 import css from './message-result.css';
@@ -17,7 +16,7 @@
 
 type MessageResultProps = {
   +item: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +scrollable: boolean,
 };
 
diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js
--- a/web/input/input-state-container.react.js
+++ b/web/input/input-state-container.react.js
@@ -73,7 +73,6 @@
 import type { RawImagesMessageInfo } from 'lib/types/messages/images.js';
 import type { RawMediaMessageInfo } from 'lib/types/messages/media.js';
 import type { RawTextMessageInfo } from 'lib/types/messages/text.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import type { Dispatch } from 'lib/types/redux-types.js';
 import { reportTypes } from 'lib/types/report-types.js';
 import { threadTypes } from 'lib/types/thread-types-enum.js';
@@ -81,6 +80,7 @@
   type ClientNewThreadRequest,
   type NewThreadResult,
   type LegacyThreadInfo,
+  type ThreadInfo,
 } from 'lib/types/thread-types.js';
 import {
   type DispatchActionPromise,
@@ -566,9 +566,7 @@
     }
   }
 
-  startThreadCreation(
-    threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
-  ): Promise<string> {
+  startThreadCreation(threadInfo: ThreadInfo): Promise<string> {
     if (!threadIsPending(threadInfo.id)) {
       return Promise.resolve(threadInfo.id);
     }
@@ -1244,8 +1242,8 @@
 
   async sendTextMessage(
     messageInfo: RawTextMessageInfo,
-    inputThreadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
-    parentThreadInfo: ?LegacyThreadInfo | ?MinimallyEncodedThreadInfo,
+    inputThreadInfo: ThreadInfo,
+    parentThreadInfo: ?ThreadInfo,
   ) {
     this.props.sendCallbacks.forEach(callback => callback());
 
@@ -1342,8 +1340,8 @@
 
   async sendTextMessageAction(
     messageInfo: RawTextMessageInfo,
-    threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
-    parentThreadInfo: ?LegacyThreadInfo | ?MinimallyEncodedThreadInfo,
+    threadInfo: ThreadInfo,
+    parentThreadInfo: ?ThreadInfo,
   ): Promise<SendMessagePayload> {
     try {
       await this.props.textMessageCreationSideEffectsFunc(
diff --git a/web/input/input-state.js b/web/input/input-state.js
--- a/web/input/input-state.js
+++ b/web/input/input-state.js
@@ -9,11 +9,10 @@
   type MediaMissionStep,
 } from 'lib/types/media-types.js';
 import type { RawTextMessageInfo } from 'lib/types/messages/text.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import type {
-  LegacyThreadInfo,
   ChatMentionCandidates,
   RelativeMemberInfo,
+  ThreadInfo,
 } from 'lib/types/thread-types.js';
 
 export type PendingMultimediaUpload = {
@@ -64,25 +63,22 @@
   +draft: string,
   +textCursorPosition: number,
   +appendFiles: (
-    threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+    threadInfo: ThreadInfo,
     files: $ReadOnlyArray<File>,
   ) => Promise<boolean>,
   +cancelPendingUpload: (localUploadID: string) => void,
   +sendTextMessage: (
     messageInfo: RawTextMessageInfo,
-    threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
-    parentThreadInfo: ?LegacyThreadInfo | ?MinimallyEncodedThreadInfo,
+    threadInfo: ThreadInfo,
+    parentThreadInfo: ?ThreadInfo,
   ) => Promise<void>,
-  +createMultimediaMessage: (
-    localID: number,
-    threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
-  ) => void,
+  +createMultimediaMessage: (localID: number, threadInfo: ThreadInfo) => void,
   +setDraft: (draft: string) => void,
   +setTextCursorPosition: (newPosition: number) => void,
   +messageHasUploadFailure: (localMessageID: string) => boolean,
   +retryMultimediaMessage: (
     localMessageID: string,
-    threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+    threadInfo: ThreadInfo,
   ) => void,
   +addReply: (text: string) => void,
   +addReplyListener: ((message: string) => void) => void,
diff --git a/web/invite-links/manage/edit-link-modal.react.js b/web/invite-links/manage/edit-link-modal.react.js
--- a/web/invite-links/manage/edit-link-modal.react.js
+++ b/web/invite-links/manage/edit-link-modal.react.js
@@ -11,8 +11,7 @@
   inviteLinkErrorMessages,
 } from 'lib/shared/invite-links.js';
 import type { InviteLink } from 'lib/types/link-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import css from './manage-invite-links-modal.css';
 import Button from '../../components/button.react.js';
@@ -23,7 +22,7 @@
   +inviteLink: ?InviteLink,
   +enterViewMode: () => mixed,
   +enterDisableMode: () => mixed,
-  +community: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +community: ThreadInfo,
 };
 
 const disableButtonColor = {
diff --git a/web/markdown/rules.react.js b/web/markdown/rules.react.js
--- a/web/markdown/rules.react.js
+++ b/web/markdown/rules.react.js
@@ -6,11 +6,10 @@
 
 import * as SharedMarkdown from 'lib/shared/markdown.js';
 import { chatMentionRegex } from 'lib/shared/mention-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import type {
-  LegacyThreadInfo,
   ChatMentionCandidates,
   RelativeMemberInfo,
+  ThreadInfo,
 } from 'lib/types/thread-types.js';
 
 import MarkdownChatMention from './markdown-chat-mention.react.js';
@@ -166,7 +165,7 @@
 });
 
 function useTextMessageRulesFunc(
-  threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  threadInfo: ThreadInfo,
   chatMentionCandidates: ChatMentionCandidates,
 ): boolean => MarkdownRules {
   const { members } = threadInfo;
diff --git a/web/modals/chat/message-results-modal.react.js b/web/modals/chat/message-results-modal.react.js
--- a/web/modals/chat/message-results-modal.react.js
+++ b/web/modals/chat/message-results-modal.react.js
@@ -18,8 +18,7 @@
   modifyItemForResultScreen,
 } from 'lib/shared/message-utils.js';
 import type { RawMessageInfo } from 'lib/types/message-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import { type ThreadInfo } from 'lib/types/thread-types.js';
 import { useDispatchActionPromise } from 'lib/utils/action-utils.js';
 
 import css from './message-results-modal.css';
@@ -29,7 +28,7 @@
 import Modal from '../modal.react.js';
 
 type MessageResultsModalProps = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +modalName: string,
 };
 
diff --git a/web/modals/chat/sidebar-promote-modal.react.js b/web/modals/chat/sidebar-promote-modal.react.js
--- a/web/modals/chat/sidebar-promote-modal.react.js
+++ b/web/modals/chat/sidebar-promote-modal.react.js
@@ -2,8 +2,7 @@
 
 import * as React from 'react';
 
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js';
 
 import css from './sidebar-promote-modal.css';
@@ -13,7 +12,7 @@
 type Props = {
   +onClose: () => void,
   +onConfirm: () => void,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function SidebarPromoteModal(props: Props): React.Node {
diff --git a/web/modals/chat/toggle-pin-modal.react.js b/web/modals/chat/toggle-pin-modal.react.js
--- a/web/modals/chat/toggle-pin-modal.react.js
+++ b/web/modals/chat/toggle-pin-modal.react.js
@@ -11,8 +11,7 @@
 import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
 import { modifyItemForResultScreen } from 'lib/shared/message-utils.js';
 import type { RawMessageInfo } from 'lib/types/message-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { useDispatchActionPromise } from 'lib/utils/action-utils.js';
 
 import css from './toggle-pin-modal.css';
@@ -22,7 +21,7 @@
 
 type TogglePinModalProps = {
   +item: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function TogglePinModal(props: TogglePinModalProps): React.Node {
diff --git a/web/modals/search/message-search-modal.react.js b/web/modals/search/message-search-modal.react.js
--- a/web/modals/search/message-search-modal.react.js
+++ b/web/modals/search/message-search-modal.react.js
@@ -4,8 +4,7 @@
 
 import { useModalContext } from 'lib/components/modal-provider.react.js';
 import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js';
 
 import css from './message-search-modal.css';
@@ -19,7 +18,7 @@
 import Modal from '../modal.react.js';
 
 type ContentProps = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function MessageSearchModal(props: ContentProps): React.Node {
diff --git a/web/modals/search/message-search-utils.react.js b/web/modals/search/message-search-utils.react.js
--- a/web/modals/search/message-search-utils.react.js
+++ b/web/modals/search/message-search-utils.react.js
@@ -10,13 +10,12 @@
 } from 'lib/shared/message-utils.js';
 import { filterChatMessageInfosForSearch } from 'lib/shared/search-utils.js';
 import type { RawMessageInfo } from 'lib/types/message-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import { useSelector } from '../../redux/redux-utils.js';
 
 function useParseSearchResults(
-  threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  threadInfo: ThreadInfo,
   searchResults: $ReadOnlyArray<RawMessageInfo>,
 ): $ReadOnlyArray<ChatMessageInfoItem> {
   const userInfos = useSelector(state => state.userStore.userInfos);
diff --git a/web/modals/threads/confirm-leave-thread-modal.react.js b/web/modals/threads/confirm-leave-thread-modal.react.js
--- a/web/modals/threads/confirm-leave-thread-modal.react.js
+++ b/web/modals/threads/confirm-leave-thread-modal.react.js
@@ -2,8 +2,7 @@
 
 import * as React from 'react';
 
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import { type ThreadInfo } from 'lib/types/thread-types.js';
 import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js';
 
 import css from './confirm-leave-thread-modal.css';
@@ -11,7 +10,7 @@
 import Modal from '../modal.react.js';
 
 type Props = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +onClose: () => void,
   +onConfirm: () => void,
 };
diff --git a/web/modals/threads/create/compose-subchannel-modal.react.js b/web/modals/threads/create/compose-subchannel-modal.react.js
--- a/web/modals/threads/create/compose-subchannel-modal.react.js
+++ b/web/modals/threads/create/compose-subchannel-modal.react.js
@@ -7,9 +7,8 @@
   newThreadActionTypes,
 } from 'lib/actions/thread-actions.js';
 import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadTypes } from 'lib/types/thread-types-enum.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { useDispatchActionPromise } from 'lib/utils/action-utils.js';
 import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js';
 import { useDispatch } from 'lib/utils/redux-utils.js';
@@ -27,7 +26,7 @@
 
 type Props = {
   +onClose: () => void,
-  +parentThreadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +parentThreadInfo: ThreadInfo,
 };
 
 const getThreadType = (visibility: VisibilityType, announcement: boolean) => {
diff --git a/web/modals/threads/create/steps/subchannel-members-list.react.js b/web/modals/threads/create/steps/subchannel-members-list.react.js
--- a/web/modals/threads/create/steps/subchannel-members-list.react.js
+++ b/web/modals/threads/create/steps/subchannel-members-list.react.js
@@ -4,11 +4,7 @@
 
 import { useENSNames } from 'lib/hooks/ens-cache.js';
 import { stringForUser } from 'lib/shared/user-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type {
-  RelativeMemberInfo,
-  LegacyThreadInfo,
-} from 'lib/types/thread-types.js';
+import type { RelativeMemberInfo, ThreadInfo } from 'lib/types/thread-types.js';
 import type { UserListItem } from 'lib/types/user-types.js';
 
 import { useSelector } from '../../../../redux/redux-utils.js';
@@ -17,8 +13,8 @@
 type Props = {
   +searchText: string,
   +searchResult: $ReadOnlySet<string>,
-  +communityThreadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
-  +parentThreadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +communityThreadInfo: ThreadInfo,
+  +parentThreadInfo: ThreadInfo,
   +selectedUsers: $ReadOnlySet<string>,
   +toggleUserSelection: (userID: string) => void,
 };
diff --git a/web/modals/threads/gallery/thread-settings-media-gallery.react.js b/web/modals/threads/gallery/thread-settings-media-gallery.react.js
--- a/web/modals/threads/gallery/thread-settings-media-gallery.react.js
+++ b/web/modals/threads/gallery/thread-settings-media-gallery.react.js
@@ -10,8 +10,7 @@
   encryptedVideoThumbnailBlobURI,
 } from 'lib/media/media-utils.js';
 import type { Media } from 'lib/types/media-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import GalleryItem from './thread-settings-media-gallery-item.react.js';
 import css from './thread-settings-media-gallery.css';
@@ -23,7 +22,7 @@
 
 type ThreadSettingsMediaGalleryModalProps = {
   +onClose: () => void,
-  +parentThreadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +parentThreadInfo: ThreadInfo,
   +limit: number,
   +activeTab: MediaGalleryTab,
 };
diff --git a/web/modals/threads/members/change-member-role-modal.react.js b/web/modals/threads/members/change-member-role-modal.react.js
--- a/web/modals/threads/members/change-member-role-modal.react.js
+++ b/web/modals/threads/members/change-member-role-modal.react.js
@@ -11,11 +11,7 @@
 import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
 import { otherUsersButNoOtherAdmins } from 'lib/selectors/thread-selectors.js';
 import { roleIsAdminRole } from 'lib/shared/thread-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type {
-  LegacyThreadInfo,
-  RelativeMemberInfo,
-} from 'lib/types/thread-types';
+import type { RelativeMemberInfo, ThreadInfo } from 'lib/types/thread-types';
 import { useDispatchActionPromise } from 'lib/utils/action-utils.js';
 import { values } from 'lib/utils/objects.js';
 
@@ -29,7 +25,7 @@
 
 type ChangeMemberRoleModalProps = {
   +memberInfo: RelativeMemberInfo,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function ChangeMemberRoleModal(props: ChangeMemberRoleModalProps): React.Node {
diff --git a/web/modals/threads/members/member.react.js b/web/modals/threads/members/member.react.js
--- a/web/modals/threads/members/member.react.js
+++ b/web/modals/threads/members/member.react.js
@@ -11,11 +11,7 @@
 } from 'lib/shared/thread-utils.js';
 import { stringForUser } from 'lib/shared/user-utils.js';
 import type { SetState } from 'lib/types/hook-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type {
-  LegacyThreadInfo,
-  RelativeMemberInfo,
-} from 'lib/types/thread-types.js';
+import type { RelativeMemberInfo, ThreadInfo } from 'lib/types/thread-types.js';
 import { useDispatchActionPromise } from 'lib/utils/action-utils.js';
 import { useRolesFromCommunityThreadInfo } from 'lib/utils/role-utils.js';
 
@@ -32,7 +28,7 @@
 
 type Props = {
   +memberInfo: RelativeMemberInfo,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +setOpenMenu: SetState<?string>,
 };
 
diff --git a/web/modals/threads/members/members-list.react.js b/web/modals/threads/members/members-list.react.js
--- a/web/modals/threads/members/members-list.react.js
+++ b/web/modals/threads/members/members-list.react.js
@@ -7,17 +7,16 @@
 
 import { useENSNames } from 'lib/hooks/ens-cache.js';
 import { stringForUser } from 'lib/shared/user-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import {
-  type LegacyThreadInfo,
   type RelativeMemberInfo,
+  type ThreadInfo,
 } from 'lib/types/thread-types.js';
 
 import ThreadMember from './member.react.js';
 import css from './members-modal.css';
 
 type Props = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +threadMembers: $ReadOnlyArray<RelativeMemberInfo>,
 };
 
diff --git a/web/modals/threads/settings/thread-settings-delete-confirmation-modal.react.js b/web/modals/threads/settings/thread-settings-delete-confirmation-modal.react.js
--- a/web/modals/threads/settings/thread-settings-delete-confirmation-modal.react.js
+++ b/web/modals/threads/settings/thread-settings-delete-confirmation-modal.react.js
@@ -4,15 +4,14 @@
 
 import { useModalContext } from 'lib/components/modal-provider.react.js';
 import { getThreadsToDeleteText } from 'lib/shared/thread-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types';
+import type { ThreadInfo } from 'lib/types/thread-types';
 
 import css from './thread-settings-delete-confirmation-modal.css';
 import Button from '../../../components/button.react.js';
 import Modal from '../../modal.react.js';
 
 type BaseProps = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +onConfirmation: () => mixed,
 };
 
diff --git a/web/modals/threads/settings/thread-settings-delete-tab.react.js b/web/modals/threads/settings/thread-settings-delete-tab.react.js
--- a/web/modals/threads/settings/thread-settings-delete-tab.react.js
+++ b/web/modals/threads/settings/thread-settings-delete-tab.react.js
@@ -10,8 +10,7 @@
 import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
 import { containedThreadInfos } from 'lib/selectors/thread-selectors.js';
 import { type SetState } from 'lib/types/hook-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { useDispatchActionPromise } from 'lib/utils/action-utils.js';
 
 import SubmitSection from './submit-section.react.js';
@@ -22,7 +21,7 @@
 
 type ThreadSettingsDeleteTabProps = {
   +threadSettingsOperationInProgress: boolean,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +setErrorMessage: SetState<?string>,
   +errorMessage?: ?string,
 };
diff --git a/web/modals/threads/settings/thread-settings-general-tab.react.js b/web/modals/threads/settings/thread-settings-general-tab.react.js
--- a/web/modals/threads/settings/thread-settings-general-tab.react.js
+++ b/web/modals/threads/settings/thread-settings-general-tab.react.js
@@ -9,12 +9,8 @@
 } from 'lib/actions/thread-actions.js';
 import { threadHasPermission } from 'lib/shared/thread-utils.js';
 import { type SetState } from 'lib/types/hook-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadPermissions } from 'lib/types/thread-permission-types.js';
-import {
-  type LegacyThreadInfo,
-  type ThreadChanges,
-} from 'lib/types/thread-types.js';
+import { type ThreadChanges, type ThreadInfo } from 'lib/types/thread-types.js';
 import { useDispatchActionPromise } from 'lib/utils/action-utils.js';
 import { firstLine } from 'lib/utils/string-utils.js';
 import { chatNameMaxLength } from 'lib/utils/validation-utils.js';
@@ -28,7 +24,7 @@
 
 type ThreadSettingsGeneralTabProps = {
   +threadSettingsOperationInProgress: boolean,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +threadNamePlaceholder: string,
   +queuedChanges: ThreadChanges,
   +setQueuedChanges: SetState<ThreadChanges>,
diff --git a/web/modals/threads/settings/thread-settings-modal.react.js b/web/modals/threads/settings/thread-settings-modal.react.js
--- a/web/modals/threads/settings/thread-settings-modal.react.js
+++ b/web/modals/threads/settings/thread-settings-modal.react.js
@@ -16,13 +16,13 @@
   getSingleOtherUser,
   threadUIName,
 } from 'lib/shared/thread-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import type { RelationshipButton } from 'lib/types/relationship-types.js';
 import { threadPermissions } from 'lib/types/thread-permission-types.js';
 import { threadTypes } from 'lib/types/thread-types-enum.js';
 import {
   type LegacyThreadInfo,
   type ThreadChanges,
+  type ThreadInfo,
 } from 'lib/types/thread-types.js';
 import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js';
 
@@ -101,7 +101,7 @@
     const hasPermissionForTab = React.useCallback(
       // ESLint doesn't recognize that invariant always throws
       // eslint-disable-next-line consistent-return
-      (thread: LegacyThreadInfo | MinimallyEncodedThreadInfo, tab: TabType) => {
+      (thread: ThreadInfo, tab: TabType) => {
         if (tab === 'general') {
           return (
             threadHasPermission(thread, threadPermissions.EDIT_THREAD_NAME) ||
diff --git a/web/modals/threads/settings/thread-settings-privacy-tab.react.js b/web/modals/threads/settings/thread-settings-privacy-tab.react.js
--- a/web/modals/threads/settings/thread-settings-privacy-tab.react.js
+++ b/web/modals/threads/settings/thread-settings-privacy-tab.react.js
@@ -10,12 +10,8 @@
 import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
 import { threadTypeDescriptions } from 'lib/shared/thread-utils.js';
 import { type SetState } from 'lib/types/hook-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadTypes } from 'lib/types/thread-types-enum.js';
-import {
-  type LegacyThreadInfo,
-  type ThreadChanges,
-} from 'lib/types/thread-types.js';
+import { type ThreadChanges, type ThreadInfo } from 'lib/types/thread-types.js';
 import { useDispatchActionPromise } from 'lib/utils/action-utils.js';
 
 import SubmitSection from './submit-section.react.js';
@@ -42,7 +38,7 @@
 
 type ThreadSettingsPrivacyTabProps = {
   +threadSettingsOperationInProgress: boolean,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
   +queuedChanges: ThreadChanges,
   +setQueuedChanges: SetState<ThreadChanges>,
   +setErrorMessage: SetState<?string>,
diff --git a/web/modals/user-profile/user-profile-menu.react.js b/web/modals/user-profile/user-profile-menu.react.js
--- a/web/modals/user-profile/user-profile-menu.react.js
+++ b/web/modals/user-profile/user-profile-menu.react.js
@@ -6,9 +6,8 @@
 
 import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
 import { useRelationshipPrompt } from 'lib/hooks/relationship-prompt.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { userRelationshipStatus } from 'lib/types/relationship-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types';
+import type { ThreadInfo } from 'lib/types/thread-types';
 
 import MenuItem from '../../components/menu-item.react.js';
 import Menu from '../../components/menu.react.js';
@@ -22,7 +21,7 @@
 const unblockIcon = <FontAwesomeIcon icon={faUserShield} />;
 
 type Props = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function UserProfileMenu(props: Props): React.Node {
diff --git a/web/modals/user-profile/user-profile-message-button.react.js b/web/modals/user-profile/user-profile-message-button.react.js
--- a/web/modals/user-profile/user-profile-message-button.react.js
+++ b/web/modals/user-profile/user-profile-message-button.react.js
@@ -4,15 +4,14 @@
 
 import { useModalContext } from 'lib/components/modal-provider.react.js';
 import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import css from './user-profile.css';
 import Button from '../../components/button.react.js';
 import { useOnClickThread } from '../../selectors/thread-selectors.js';
 
 type Props = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function UserProfileMessageButton(props: Props): React.Node {
diff --git a/web/navigation-panels/chat-thread-ancestors.react.js b/web/navigation-panels/chat-thread-ancestors.react.js
--- a/web/navigation-panels/chat-thread-ancestors.react.js
+++ b/web/navigation-panels/chat-thread-ancestors.react.js
@@ -5,14 +5,13 @@
 import { ChevronRight } from 'react-feather';
 
 import { useAncestorThreads } from 'lib/shared/ancestor-threads.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js';
 
 import css from './chat-thread-ancestors.css';
 
 type ThreadAncestorsProps = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 function ThreadAncestors(props: ThreadAncestorsProps): React.Node {
   const { threadInfo } = props;
diff --git a/web/navigation-panels/nav-state-info-bar.react.js b/web/navigation-panels/nav-state-info-bar.react.js
--- a/web/navigation-panels/nav-state-info-bar.react.js
+++ b/web/navigation-panels/nav-state-info-bar.react.js
@@ -3,15 +3,14 @@
 import classnames from 'classnames';
 import * as React from 'react';
 
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import ThreadAncestors from './chat-thread-ancestors.react.js';
 import css from './nav-state-info-bar.css';
 import ThreadAvatar from '../avatars/thread-avatar.react.js';
 
 type NavStateInfoBarProps = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 function NavStateInfoBar(props: NavStateInfoBarProps): React.Node {
   const { threadInfo } = props;
@@ -27,7 +26,7 @@
 }
 
 type PossiblyEmptyNavStateInfoBarProps = {
-  +threadInfoInput: ?LegacyThreadInfo | ?MinimallyEncodedThreadInfo,
+  +threadInfoInput: ?ThreadInfo,
 };
 function PossiblyEmptyNavStateInfoBar(
   props: PossiblyEmptyNavStateInfoBarProps,
diff --git a/web/selectors/thread-selectors.js b/web/selectors/thread-selectors.js
--- a/web/selectors/thread-selectors.js
+++ b/web/selectors/thread-selectors.js
@@ -15,10 +15,9 @@
   ComposableMessageInfo,
   RobotextMessageInfo,
 } from 'lib/types/message-types.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import type {
-  LegacyThreadInfo,
   LegacyRawThreadInfos,
+  ThreadInfo,
 } from 'lib/types/thread-types.js';
 import { values } from 'lib/utils/objects.js';
 import { useDispatch } from 'lib/utils/redux-utils.js';
@@ -29,7 +28,7 @@
 import { useSelector } from '../redux/redux-utils.js';
 
 function useOnClickThread(
-  thread: ?LegacyThreadInfo | ?MinimallyEncodedThreadInfo,
+  thread: ?ThreadInfo,
 ): (event: SyntheticEvent<HTMLElement>) => void {
   const dispatch = useDispatch();
   return React.useCallback(
@@ -69,7 +68,7 @@
 
 function useOnClickPendingSidebar(
   messageInfo: ComposableMessageInfo | RobotextMessageInfo,
-  threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  threadInfo: ThreadInfo,
 ): (event: SyntheticEvent<HTMLElement>) => mixed {
   const dispatch = useDispatch();
   const loggedInUserInfo = useLoggedInUserInfo();
diff --git a/web/sidebar/community-drawer-item-community-handlers.react.js b/web/sidebar/community-drawer-item-community-handlers.react.js
--- a/web/sidebar/community-drawer-item-community-handlers.react.js
+++ b/web/sidebar/community-drawer-item-community-handlers.react.js
@@ -7,8 +7,7 @@
   updateChatCommunityFilter,
   clearChatCommunityFilter,
 } from 'lib/actions/community-actions.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { useDispatch } from 'lib/utils/redux-utils.js';
 
 import type { CommunityDrawerItemCommunityHandler } from './community-drawer-item-handler.react.js';
@@ -22,7 +21,7 @@
 
 export type HandlerProps = {
   +setHandler: (handler: CommunityDrawerItemCommunityHandler) => void,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function ChatDrawerItemCommunityHandler(props: HandlerProps): React.Node {
diff --git a/web/sidebar/community-drawer-item-handlers.react.js b/web/sidebar/community-drawer-item-handlers.react.js
--- a/web/sidebar/community-drawer-item-handlers.react.js
+++ b/web/sidebar/community-drawer-item-handlers.react.js
@@ -2,8 +2,7 @@
 
 import * as React from 'react';
 
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import type { CommunityDrawerItemHandler } from './community-drawer-item-handler.react.js';
 import { useCommunityIsPickedCalendar } from '../selectors/calendar-selectors.js';
@@ -15,7 +14,7 @@
 
 export type HandlerProps = {
   +setHandler: (handler: CommunityDrawerItemHandler) => void,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function ChatDrawerItemHandler(props: HandlerProps): React.Node {
diff --git a/web/sidebar/community-drawer-utils.react.js b/web/sidebar/community-drawer-utils.react.js
--- a/web/sidebar/community-drawer-utils.react.js
+++ b/web/sidebar/community-drawer-utils.react.js
@@ -2,8 +2,7 @@
 
 import * as React from 'react';
 
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types';
+import type { ThreadInfo } from 'lib/types/thread-types';
 import type { CommunityDrawerItemData } from 'lib/utils/drawer-utils.react';
 
 import css from './community-drawer-item.css';
@@ -28,7 +27,7 @@
   hasSubchannelsButton: boolean,
   itemChildren: $ReadOnlyArray<CommunityDrawerItemData<string>>,
   paddingLeft: number,
-  threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  threadInfo: ThreadInfo,
   expandable: boolean,
   handlerType: NavigationTab,
 }): React.Node {
diff --git a/web/sidebar/subchannels-button.react.js b/web/sidebar/subchannels-button.react.js
--- a/web/sidebar/subchannels-button.react.js
+++ b/web/sidebar/subchannels-button.react.js
@@ -4,15 +4,14 @@
 import { CornerDownRight } from 'react-feather';
 
 import { useModalContext } from 'lib/components/modal-provider.react.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 
 import css from './subchannels-button.css';
 import Button from '../components/button.react.js';
 import SubchannelsModal from '../modals/threads/subchannels/subchannels-modal.react.js';
 
 type Props = {
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function SubchannelsButton(props: Props): React.Node {
diff --git a/web/utils/thread-utils.js b/web/utils/thread-utils.js
--- a/web/utils/thread-utils.js
+++ b/web/utils/thread-utils.js
@@ -10,9 +10,8 @@
   createPendingThread,
   useExistingThreadInfoFinder,
 } from 'lib/shared/thread-utils.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadTypes } from 'lib/types/thread-types-enum.js';
-import { type LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import type { AccountUserInfo } from 'lib/types/user-types.js';
 
 import { useSelector } from '../redux/redux-utils.js';
@@ -40,7 +39,7 @@
 
 function useThreadInfoForPossiblyPendingThread(
   activeChatThreadID: ?string,
-): ?LegacyThreadInfo | ?MinimallyEncodedThreadInfo {
+): ?ThreadInfo {
   const { isChatCreation, selectedUserInfos } = useInfosForPendingThread();
 
   const loggedInUserInfo = useLoggedInUserInfo();
diff --git a/web/utils/tooltip-action-utils.js b/web/utils/tooltip-action-utils.js
--- a/web/utils/tooltip-action-utils.js
+++ b/web/utils/tooltip-action-utils.js
@@ -17,9 +17,8 @@
   useSidebarExistsOrCanBeCreated,
 } from 'lib/shared/thread-utils.js';
 import { messageTypes } from 'lib/types/message-types-enum.js';
-import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadPermissions } from 'lib/types/thread-permission-types.js';
-import type { LegacyThreadInfo } from 'lib/types/thread-types.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
 import { longAbsoluteDate } from 'lib/utils/date-utils.js';
 import { canToggleMessagePin } from 'lib/utils/toggle-pin-utils.js';
 
@@ -128,7 +127,7 @@
 
 function useMessageTooltipSidebarAction(
   item: ChatMessageInfoItem,
-  threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  threadInfo: ThreadInfo,
 ): ?MessageTooltipAction {
   const { threadCreatedFromMessage, messageInfo } = item;
   const { popModal } = useModalContext();
@@ -170,7 +169,7 @@
 
 function useMessageTooltipReplyAction(
   item: ChatMessageInfoItem,
-  threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  threadInfo: ThreadInfo,
 ): ?MessageTooltipAction {
   const { messageInfo } = item;
   const { popModal } = useModalContext();
@@ -235,7 +234,7 @@
 
 function useMessageReactAction(
   item: ChatMessageInfoItem,
-  threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  threadInfo: ThreadInfo,
 ): ?MessageTooltipAction {
   const { messageInfo } = item;
 
@@ -270,7 +269,7 @@
 
 function useMessageTogglePinAction(
   item: ChatMessageInfoItem,
-  threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  threadInfo: ThreadInfo,
 ): ?MessageTooltipAction {
   const { pushModal } = useModalContext();
   const { messageInfo, isPinned } = item;
@@ -306,7 +305,7 @@
 
 function useMessageEditAction(
   item: ChatMessageInfoItem,
-  threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  threadInfo: ThreadInfo,
 ): ?MessageTooltipAction {
   const { messageInfo } = item;
 
@@ -349,7 +348,7 @@
 
 function useMessageTooltipActions(
   item: ChatMessageInfoItem,
-  threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  threadInfo: ThreadInfo,
 ): $ReadOnlyArray<MessageTooltipAction> {
   const sidebarAction = useMessageTooltipSidebarAction(item, threadInfo);
   const replyAction = useMessageTooltipReplyAction(item, threadInfo);
@@ -386,7 +385,7 @@
 type UseMessageTooltipArgs = {
   +availablePositions: $ReadOnlyArray<TooltipPosition>,
   +item: ChatMessageInfoItem,
-  +threadInfo: LegacyThreadInfo | MinimallyEncodedThreadInfo,
+  +threadInfo: ThreadInfo,
 };
 
 function useMessageTooltip({