diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,56 @@
-# 2.1.1.0
+# 2.3.0.0 (2026-10-09)
+* [#158](https://github.com/MercuryTechnologies/slack-web/pull/158),
+  [#159](https://github.com/MercuryTechnologies/slack-web/pull/159)
+  Decode the optional `is_bot` field on user objects.
+
+  Breaking change: `User` has a new `userIsBot :: Maybe Bool` field.
+* [#160](https://github.com/MercuryTechnologies/slack-web/pull/160)
+  Add cursor-based pagination and page-size control to `conversationsMembers`.
+
+  Breaking change: `MembersReq` has new `membersReqCursor` and `membersReqLimit`
+  fields; `MembersRsp` has a new `membersRspResponseMetadata` field.
+* [#155](https://github.com/MercuryTechnologies/slack-web/pull/155)
+  Replace the `data-default-class` dependency with `data-default`.
+* [#164](https://github.com/MercuryTechnologies/slack-web/pull/164),
+  [#165](https://github.com/MercuryTechnologies/slack-web/pull/165)
+  Include more information in Block Kit parse errors. If an unexpected value is
+  found, it will now include the invalid value as part of the error.
+
+  Before:
+
+      Unknown SlackActionComponent type, must be one of ['button']
+
+  After:
+
+      Unknown SlackActionComponent type 'weird_type', must be one of ['button']
+
+* [#168](https://github.com/MercuryTechnologies/slack-web/pull/168)
+  Parse rich-text `message_mention` elements as `RichItemMessageMention`.
+  These elements were previously returned as `RichItemOther`.
+
+  Breaking change: `RichItem` has a new `RichItemMessageMention` constructor.
+* [#169](https://github.com/MercuryTechnologies/slack-web/pull/169)
+  Introduce `RichTextSection` for `rich_text_section` objects.
+
+  Breaking change: `RichTextSectionItemRichText` now wraps `RichTextSection`
+  instead of `[RichItem]`.
+* [#170](https://github.com/MercuryTechnologies/slack-web/pull/170)
+  Breaking change: `RichTextSectionItem` has new `RichTextSectionItemList`,
+  `RichTextSectionItemQuote`, and `RichTextSectionItemPreformatted` constructors.
+
+# 2.2.3.0 (2025-09-15)
+* [#156](https://github.com/MercuryTechnologies/slack-web/pull/156)
+  Implement `message_deleted` event.
+
+# 2.2.2.0 (2025-09-15)
+* [#153](https://github.com/MercuryTechnologies/slack-web/pull/153)
+  Implement `channel_shared` and `channel_unshared` events.
+
+# 2.2.1.0 (2025-09-15)
+* [#151](https://github.com/MercuryTechnologies/slack-web/pull/151)
+  Implement `conversations.member` API method.
+
+# 2.2.0.0 (2025-03-21)
 * [#145](https://github.com/MercuryTechnologies/slack-web/pull/145)
   Implement `conversations.info` API method.
 
diff --git a/slack-web.cabal b/slack-web.cabal
--- a/slack-web.cabal
+++ b/slack-web.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name: slack-web
-version: 2.2.0.0
+version: 2.3.0.0
 
 build-type: Simple
 
@@ -153,12 +153,12 @@
     , classy-prelude
     , containers
     , crypton
-    , data-default-class
+    , data-default
     , deepseq
     , either
     , errors
     , hashable
-    , http-api-data >= 0.3 && < 0.7
+    , http-api-data >= 0.3 && < 0.8
     , http-client >= 0.5 && < 0.8
     , http-client-tls >= 0.3 && < 0.4
     , megaparsec >= 5.0 && < 10
@@ -197,6 +197,7 @@
       Web.Slack.ChatSpec
       Web.Slack.Files.TypesSpec
       Web.Slack.InternalSpec
+      Web.Slack.UserSpec
       Web.Slack.UsersConversationsSpec
       Web.Slack.Experimental.RequestVerificationSpec
       Web.Slack.Experimental.Events.TypesSpec
diff --git a/src/Web/Slack/Conversation.hs b/src/Web/Slack/Conversation.hs
--- a/src/Web/Slack/Conversation.hs
+++ b/src/Web/Slack/Conversation.hs
@@ -44,6 +44,11 @@
   JoinRsp (..),
   conversationsJoin,
   conversationsJoin_,
+  MembersReq (..),
+  mkMembersReq,
+  MembersRsp (..),
+  conversationsMembers,
+  conversationsMembers_,
 ) where
 
 import Data.Aeson
@@ -475,6 +480,62 @@
 
 $(deriveJSON (jsonOpts "infoRsp") ''InfoRsp)
 
+-- | @conversations.members@ request: retrieve a conversation's members.
+--
+-- <https://api.slack.com/methods/conversations.members>
+--
+-- @since 2.2.1.0
+data MembersReq = MembersReq
+  { membersReqChannel :: ConversationId
+  , membersReqCursor :: Maybe Cursor
+  , membersReqLimit :: Maybe Int
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance NFData MembersReq
+
+$(deriveFromJSON (jsonOpts "membersReq") ''MembersReq)
+
+instance ToForm MembersReq where
+  toForm MembersReq {..} =
+    [("channel", toQueryParam membersReqChannel)]
+      <> toQueryParamIfJust "cursor" membersReqCursor
+      <> toQueryParamIfJust "limit" membersReqLimit
+
+-- | Smart constructor for 'MembersReq' with defaults.
+--
+-- @since 2.2.1.0
+mkMembersReq :: ConversationId -> MembersReq
+mkMembersReq channel =
+  MembersReq
+    { membersReqChannel = channel
+    , membersReqCursor = Nothing
+    , membersReqLimit = Nothing
+    }
+
+instance PagedRequest MembersReq where
+  setCursor c r = r {membersReqCursor = c}
+
+-- | @conversation.members@ response
+--
+-- <https://api.slack.com/methods/conversations.members>
+--
+-- @since 2.2.1.0
+data MembersRsp = MembersRsp
+  { membersRspMembers :: [UserId]
+  , membersRspResponseMetadata :: Maybe ResponseMetadata
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance NFData MembersRsp
+
+$(deriveFromJSON (jsonOpts "membersRsp") ''MembersRsp)
+
+instance PagedResponse MembersRsp where
+  type ResponseObject MembersRsp = UserId
+  getResponseData MembersRsp {membersRspMembers} = membersRspMembers
+  getResponseMetadata MembersRsp {membersRspResponseMetadata} = membersRspResponseMetadata
+
 -- | FIXME(jadel): move the rest of the Conversations API into here since the old "shoving all the API in one spot" is soft deprecated.
 -- @since 2.2.0.0
 type Api =
@@ -486,6 +547,10 @@
       :> AuthProtect "token"
       :> ReqBody '[FormUrlEncoded] JoinReq
       :> Post '[JSON] (ResponseJSON JoinRsp)
+    :<|> "conversations.members"
+      :> AuthProtect "token"
+      :> ReqBody '[FormUrlEncoded] MembersReq
+      :> Post '[JSON] (ResponseJSON MembersRsp)
 
 -- | Joins a conversation.
 --
@@ -552,12 +617,15 @@
 -- | @since 2.2.0.0
 conversationsJoin_ :: AuthenticatedRequest (AuthProtect "token") -> JoinReq -> ClientM (ResponseJSON JoinRsp)
 
+-- | @since 2.2.1.0
+conversationsMembers_ :: AuthenticatedRequest (AuthProtect "token") -> MembersReq -> ClientM (ResponseJSON MembersRsp)
+
 -- | @since 2.2.0.0
 conversationsInfo_ ::
   AuthenticatedRequest (AuthProtect "token") ->
   InfoReq ->
   ClientM (ResponseJSON InfoRsp)
-conversationsInfo_ :<|> conversationsJoin_ = client (Proxy @Api)
+conversationsInfo_ :<|> conversationsJoin_ :<|> conversationsMembers_ = client (Proxy @Api)
 
 -- | Retrieve a conversation's metadata.
 --
@@ -584,3 +652,12 @@
 conversationsJoin slackConfig req = do
   let authR = mkSlackAuthenticateReq slackConfig
   run (conversationsJoin_ authR req) . slackConfigManager $ slackConfig
+
+-- | @since 2.2.1.0
+conversationsMembers ::
+  SlackConfig ->
+  MembersReq ->
+  IO (Response MembersRsp)
+conversationsMembers slackConfig req = do
+  let authR = mkSlackAuthenticateReq slackConfig
+  run (conversationsMembers_ authR req) . slackConfigManager $ slackConfig
diff --git a/src/Web/Slack/Experimental/Blocks.hs b/src/Web/Slack/Experimental/Blocks.hs
--- a/src/Web/Slack/Experimental/Blocks.hs
+++ b/src/Web/Slack/Experimental/Blocks.hs
@@ -31,6 +31,8 @@
   RichItem (..),
   RichStyle (..),
   RichLinkAttrs (..),
+  RichMessageMention (..),
+  RichTextSection (..),
   RichTextSectionItem (..),
   RichText (..),
 
diff --git a/src/Web/Slack/Experimental/Blocks/Types.hs b/src/Web/Slack/Experimental/Blocks/Types.hs
--- a/src/Web/Slack/Experimental/Blocks/Types.hs
+++ b/src/Web/Slack/Experimental/Blocks/Types.hs
@@ -88,7 +88,7 @@
       "mrkdwn" -> do
         text <- obj .: "text"
         pure . SlackMarkdownText . SlackText $ lines text
-      _ -> fail "Unknown SlackTextObject type, must be one of ['plain_text', 'mrkdwn']"
+      _ -> fail $ "Unknown SlackTextObject type " <> show slackTextType <> ", must be one of ['plain_text', 'mrkdwn']"
 
 instance Show SlackText where
   show (SlackText arr) = show $ concat arr
@@ -216,7 +216,7 @@
           Just innerObj -> innerObj .: "text"
           Nothing -> pure Nothing
         pure $ SlackContentImage $ SlackImage slackImageTitleText slackImageAltText slackImageUrl
-      _ -> fail "Unknown SlackContent type, must be one of ['mrkdwn', 'image']"
+      _ -> fail $ "Unknown SlackContent type " <> show slackContentType <> ", must be one of ['mrkdwn', 'image']"
 
 newtype SlackContext = SlackContext [SlackContent]
   deriving newtype (Semigroup, Monoid, Eq)
@@ -289,15 +289,48 @@
   }
   deriving stock (Eq, Show)
 
--- | Seemingly only documented at
---  <https://api.slack.com/changelog/2019-09-what-they-see-is-what-you-get-and-more-and-less>
+-- | An inline reference to a message. The URL is optional; consumers can build
+-- a permalink from the channel and message timestamp in the current workspace.
 --
---  They warn of undocumented element types. Joy.
+-- Parsed as part of 'RichItemMessageMention' in incoming rich text.
+--
+-- <https://docs.slack.dev/reference/block-kit/block-elements/message-mention-element/>
+--
+-- @since 2.3.0.0
+data RichMessageMention = RichMessageMention
+  { rmmChannelId :: ConversationId
+  -- ^ Channel containing the referenced message.
+  --
+  -- @since 2.3.0.0
+  , rmmMessageTs :: Text
+  -- ^ Timestamp identifying the referenced message, preserved as Slack's text.
+  --
+  -- @since 2.3.0.0
+  , rmmThreadTs :: Maybe Text
+  -- ^ Optional @thread_ts@ timestamp supplied by Slack.
+  --
+  -- @since 2.3.0.0
+  , rmmUrl :: Maybe Text
+  -- ^ URL of the referenced message, when supplied by Slack.
+  --
+  -- @since 2.3.0.0
+  }
+  deriving stock (Eq, Show)
+
+-- | Inline content inside rich-text sections, quotes, and preformatted blocks.
+--
+-- <https://docs.slack.dev/reference/block-kit/block-elements/rich-text-section-element/>
+--
+-- Unrecognized element types are preserved as 'RichItemOther'.
 data RichItem
   = RichItemText Text RichStyle
   | RichItemChannel ConversationId
   | RichItemUser UserId RichStyle
   | RichItemLink RichLinkAttrs
+  | -- | An inline @message_mention@ reference to another message.
+    --
+    -- @since 2.3.0.0
+    RichItemMessageMention RichMessageMention
   | RichItemEmoji Emoji
   | RichItemOther Text Value
   -- FIXME(jadel): date, usergroup, team, broadcast
@@ -322,14 +355,73 @@
         text <- obj .:? "text"
         style <- obj .:? "style" .!= mempty
         pure $ RichItemLink RichLinkAttrs {..}
+      "message_mention" -> do
+        rmmChannelId <- obj .: "channel_id"
+        rmmMessageTs <- obj .: "message_ts"
+        rmmThreadTs <- obj .:? "thread_ts"
+        rmmUrl <- obj .:? "url"
+        pure $ RichItemMessageMention RichMessageMention {..}
       "user" -> do
         userId <- obj .: "user_id"
         style <- obj .:? "style" .!= mempty
         pure $ RichItemUser userId style
       _ -> pure $ RichItemOther kind (Object obj)
 
+-- | A @rich_text_section@ object containing inline 'RichItem' values.
+-- A section can appear directly in a @rich_text@ block or as an entry in a
+-- @rich_text_list@. Its JSON decoder requires @type = "rich_text_section"@.
+--
+-- t'RichTextSectionItem' represents the broader set of structural children of
+-- a rich-text block; this type represents only a section. Lists contain
+-- sections, so their entries use this narrower type.
+--
+-- <https://docs.slack.dev/reference/block-kit/block-elements/rich-text-section-element/>
+--
+-- @since 2.3.0.0
+newtype RichTextSection = RichTextSection [RichItem]
+  deriving stock (Eq, Show)
+
+instance FromJSON RichTextSection where
+  parseJSON = withObject "RichTextSection" \obj -> do
+    kind :: Text <- obj .: "type"
+    case kind of
+      "rich_text_section" -> RichTextSection <$> obj .: "elements"
+      _ -> fail $ "Unexpected RichTextSection type " <> show kind <> ", must be 'rich_text_section'"
+
+-- | Structural children of a @rich_text@ block: sections, lists, quotes, and
+-- preformatted blocks. The name refers to this broader set of containers;
+-- t'RichTextSection' represents a single @rich_text_section@, and 'RichItem'
+-- represents inline content such as text, links, and message mentions.
+--
+-- <https://docs.slack.dev/reference/block-kit/blocks/rich-text-block/>
 data RichTextSectionItem
-  = RichTextSectionItemRichText [RichItem]
+  = -- | A @rich_text_section@ containing inline items.
+    --
+    -- <https://docs.slack.dev/reference/block-kit/block-elements/rich-text-section-element/>
+    RichTextSectionItemRichText RichTextSection
+  | -- | A @rich_text_list@ whose entries are sections. The t'RichTextSection'
+    -- decoder rejects entries with any other container type.
+    -- The decoder ignores Slack's @style@, @indent@, @offset@, and @border@ fields.
+    --
+    -- <https://docs.slack.dev/reference/block-kit/block-elements/rich-text-list-element/>
+    --
+    -- @since 2.3.0.0
+    RichTextSectionItemList [RichTextSection]
+  | -- | A @rich_text_quote@ containing inline items.
+    -- The decoder ignores Slack's optional @border@ field.
+    --
+    -- <https://docs.slack.dev/reference/block-kit/block-elements/rich-text-quote-element/>
+    --
+    -- @since 2.3.0.0
+    RichTextSectionItemQuote [RichItem]
+  | -- | A @rich_text_preformatted@ code block. Slack documents text and link
+    -- elements as its contents; 'RichItem' also permits other constructors.
+    -- Border and syntax-highlighting language are not retained.
+    --
+    -- <https://docs.slack.dev/reference/block-kit/block-elements/rich-text-preformatted-element/>
+    --
+    -- @since 2.3.0.0
+    RichTextSectionItemPreformatted [RichItem]
   | RichTextSectionItemUnknown Text Value
   deriving stock (Eq, Show)
 
@@ -337,9 +429,10 @@
   parseJSON = withObject "RichTextSectionItem" \obj -> do
     kind <- obj .: "type"
     case kind of
-      "rich_text_section" -> do
-        elts <- obj .: "elements"
-        pure $ RichTextSectionItemRichText elts
+      "rich_text_section" -> RichTextSectionItemRichText <$> parseJSON (Object obj)
+      "rich_text_list" -> RichTextSectionItemList <$> obj .: "elements"
+      "rich_text_quote" -> RichTextSectionItemQuote <$> obj .: "elements"
+      "rich_text_preformatted" -> RichTextSectionItemPreformatted <$> obj .: "elements"
       _ -> pure $ RichTextSectionItemUnknown kind (Object obj)
 
 data RichText = RichText
@@ -364,7 +457,11 @@
   toJSON (SlackButtonAccessory btn) = toJSON btn
 
 instance FromJSON SlackAccessory where
-  parseJSON v = SlackButtonAccessory <$> parseJSON v
+  parseJSON = withObject "SlackAccessory" \obj -> do
+    kind :: Text <- obj .: "type"
+    case kind of
+      "button" -> SlackButtonAccessory <$> parseJSON (Object obj)
+      _ -> fail $ "Unknown SlackAccessory type " <> show kind <> ", must be one of ['button']"
 
 instance Show SlackAccessory where
   show (SlackButtonAccessory btn) = show btn
@@ -794,7 +891,7 @@
   deriving stock (Eq)
 
 instance FromJSON SlackActionComponent where
-  parseJSON = withObject "SlactActionComponent" $ \obj -> do
+  parseJSON = withObject "SlackActionComponent" $ \obj -> do
     (slackActionType :: Text) <- obj .: "type"
     case slackActionType of
       "button" -> do
@@ -805,7 +902,7 @@
         slackButtonStyle <- obj .:? "style"
         slackButtonConfirm <- obj .:? "confirm"
         pure $ SlackButton {..}
-      _ -> fail "Unknown SlackActionComponent type, must be one of ['button']"
+      _ -> fail $ "Unknown SlackActionComponent type " <> show slackActionType <> ", must be one of ['button']"
 
 instance Show SlackActionComponent where
   show SlackButton {..} = "[button " <> show slackButtonText <> "]"
diff --git a/src/Web/Slack/Experimental/Events/Types.hs b/src/Web/Slack/Experimental/Events/Types.hs
--- a/src/Web/Slack/Experimental/Events/Types.hs
+++ b/src/Web/Slack/Experimental/Events/Types.hs
@@ -244,6 +244,20 @@
 
 $(deriveFromJSON snakeCaseOptions ''MessageUpdateEvent)
 
+-- | A message was deleted from a channel or DM.
+--
+-- <https://docs.slack.dev/reference/events/message/message_deleted/>
+--
+-- @since 2.2.3.0
+data MessageDeletedEvent = MessageDeletedEvent
+  { channel :: ConversationId
+  , ts :: Text
+  , deletedTs :: Text
+  }
+  deriving stock (Show)
+
+$(deriveFromJSON snakeCaseOptions ''MessageDeletedEvent)
+
 -- | FIXME: this might be a Channel, but may also be missing some fields/have bonus
 -- because Slack is cursed.
 data CreatedChannel = CreatedChannel
@@ -283,6 +297,35 @@
 
 $(deriveFromJSON snakeCaseOptions ''ChannelLeftEvent)
 
+-- | A channel has been shared with an external workspace.
+--
+-- <https://docs.slack.dev/reference/events/channel_shared/>
+--
+-- @since 2.2.2.0
+data ChannelSharedEvent = ChannelSharedEvent
+  { connectedTeamId :: TeamId
+  , channel :: ConversationId
+  , eventTs :: Text
+  }
+  deriving stock (Show)
+
+$(deriveFromJSON snakeCaseOptions ''ChannelSharedEvent)
+
+-- | A channel has been unshared with an external workspace.
+--
+-- <https://docs.slack.dev/reference/events/channel_unshared/>
+--
+-- @since 2.2.2.0
+data ChannelUnsharedEvent = ChannelUnsharedEvent
+  { previouslyConnectedTeamId :: TeamId
+  , channel :: ConversationId
+  , isExtShared :: Bool
+  , eventTs :: Text
+  }
+  deriving stock (Show)
+
+$(deriveFromJSON snakeCaseOptions ''ChannelUnsharedEvent)
+
 -- | <https://api.slack.com/events/url_verification>
 data UrlVerificationPayload = UrlVerificationPayload
   { challenge :: Text
@@ -339,6 +382,8 @@
   = EventMessage MessageEvent
   | EventBotMessage BotMessageEvent
   | EventMessageChanged
+  | -- | @since 2.2.3.0
+    EventMessageDeleted MessageDeletedEvent
   | -- | Weird message event of subtype channel_join. Sent "sometimes", according
     -- to a random Slack blog post from 2017:
     -- <https://api.slack.com/changelog/2017-05-rethinking-channel-entrance-and-exit-events-and-messages>
@@ -347,6 +392,10 @@
     EventChannelJoinMessage
   | EventChannelCreated ChannelCreatedEvent
   | EventChannelLeft ChannelLeftEvent
+  | -- | @since 2.2.2.0
+    EventChannelShared ChannelSharedEvent
+  | -- | @since 2.2.2.0
+    EventChannelUnshared ChannelUnsharedEvent
   | -- | @since 2.1.0.0
     EventAppHomeOpened AppHomeOpenedEvent
   | EventUnknown Value
@@ -360,12 +409,15 @@
       ("message", Nothing) -> EventMessage <$> parseJSON @MessageEvent (Object obj)
       ("message", Just "bot_message") -> EventBotMessage <$> parseJSON @BotMessageEvent (Object obj)
       ("message", Just "message_changed") -> pure EventMessageChanged
+      ("message", Just "message_deleted") -> EventMessageDeleted <$> parseJSON @MessageDeletedEvent (Object obj)
       ("message", Just "channel_join") -> pure EventChannelJoinMessage
       -- n.b. these are unified since it is *identical* to a Message event with
       -- a bonus files field
       ("message", Just "file_share") -> EventMessage <$> parseJSON @MessageEvent (Object obj)
       ("channel_created", Nothing) -> EventChannelCreated <$> parseJSON (Object obj)
       ("channel_left", Nothing) -> EventChannelLeft <$> parseJSON (Object obj)
+      ("channel_shared", Nothing) -> EventChannelShared <$> parseJSON (Object obj)
+      ("channel_unshared", Nothing) -> EventChannelUnshared <$> parseJSON (Object obj)
       ("app_home_opened", Nothing) -> EventAppHomeOpened <$> parseJSON (Object obj)
       _ -> pure $ EventUnknown (Object obj)
 
diff --git a/src/Web/Slack/Internal.hs b/src/Web/Slack/Internal.hs
--- a/src/Web/Slack/Internal.hs
+++ b/src/Web/Slack/Internal.hs
@@ -1,3 +1,5 @@
+{-# OPTIONS_GHC -Wno-orphans #-}
+
 -- | Internal things in slack-web. May be changed arbitrarily!
 module Web.Slack.Internal where
 
diff --git a/src/Web/Slack/Prelude.hs b/src/Web/Slack/Prelude.hs
--- a/src/Web/Slack/Prelude.hs
+++ b/src/Web/Slack/Prelude.hs
@@ -12,7 +12,7 @@
 import ClassyPrelude hiding (link)
 import Data.Aeson (FromJSON (..), ToJSON (..), object, withObject, (.:), (.:?), (.=))
 import Data.Aeson.TH (deriveFromJSON, deriveJSON, deriveToJSON)
-import Data.Default.Class (Default (..))
+import Data.Default (Default (..))
 import Data.List.NonEmpty (NonEmpty (..))
 import Data.Proxy (Proxy (..))
 import Data.String.Conversions (cs)
diff --git a/src/Web/Slack/User.hs b/src/Web/Slack/User.hs
--- a/src/Web/Slack/User.hs
+++ b/src/Web/Slack/User.hs
@@ -55,6 +55,7 @@
   , userIsPrimaryOwner :: Maybe Bool
   , userIsRestricted :: Maybe Bool
   , userIsUltraRestricted :: Maybe Bool
+  , userIsBot :: Maybe Bool
   , userUpdated :: POSIXTime
   }
   deriving stock (Eq, Generic, Show)
diff --git a/tests/Web/Slack/ConversationSpec.hs b/tests/Web/Slack/ConversationSpec.hs
--- a/tests/Web/Slack/ConversationSpec.hs
+++ b/tests/Web/Slack/ConversationSpec.hs
@@ -116,6 +116,8 @@
     mapM_ (oneGoldenTestDecode @Conversation) ["shared_channel"]
     mapM_ (oneGoldenTestDecode @InfoRsp) ["general"]
     mapM_ (oneGoldenTestDecode @JoinRsp) ["test"]
+    mapM_ (oneGoldenTestDecode @MembersReq) ["with_limit"]
+    mapM_ (oneGoldenTestDecode @MembersRsp) ["test"]
 
   it "errors accurately if no variant matches" $ do
     let badData =
diff --git a/tests/Web/Slack/Experimental/Blocks/TypesSpec.hs b/tests/Web/Slack/Experimental/Blocks/TypesSpec.hs
--- a/tests/Web/Slack/Experimental/Blocks/TypesSpec.hs
+++ b/tests/Web/Slack/Experimental/Blocks/TypesSpec.hs
@@ -1,9 +1,12 @@
 module Web.Slack.Experimental.Blocks.TypesSpec where
 
 import Data.Aeson qualified as Aeson
+import Data.Aeson.Types (parseEither)
+import Data.Either (isLeft)
 import Data.StringVariants.NonEmptyText.Internal (pattern NonEmptyText)
 import Refined.Unsafe (reallyUnsafeRefine)
 import TestImport
+import Web.Slack.Common (ConversationId (..))
 import Web.Slack.Experimental.Blocks.Types
 
 jsonRoundtrips :: (Show a, Eq a, Aeson.ToJSON a, Aeson.FromJSON a) => a -> Spec
@@ -13,6 +16,58 @@
 
 spec :: Spec
 spec = do
+  describe "unknown component diagnostics" do
+    it "reports the rejected text object type" do
+      Aeson.eitherDecode @SlackTextObject "{\"type\":\"unexpected_text\"}"
+        `shouldBe` Left "Error in $: Unknown SlackTextObject type \"unexpected_text\", must be one of ['plain_text', 'mrkdwn']"
+
+    it "reports the rejected content type at its nested JSON path" do
+      Aeson.eitherDecode @SlackBlock "{\"type\":\"context\",\"elements\":[{\"type\":\"unexpected_content\"}]}"
+        `shouldBe` Left "Error in $.elements: Unknown SlackContent type \"unexpected_content\", must be one of ['mrkdwn', 'image']"
+
+    it "reports the rejected action component type at its nested JSON path" do
+      Aeson.eitherDecode @SlackBlock "{\"type\":\"actions\",\"elements\":[{\"type\":\"static_select\",\"action_id\":\"select\"}]}"
+        `shouldBe` Left "Error in $.elements[0]: Unknown SlackActionComponent type \"static_select\", must be one of ['button']"
+
+    it "reports the rejected accessory type before requiring action fields" do
+      Aeson.eitherDecode @SlackAccessory "{\"type\":\"image\",\"image_url\":\"https://example.com/image.png\",\"alt_text\":\"example\"}"
+        `shouldBe` Left "Error in $: Unknown SlackAccessory type \"image\", must be one of ['button']"
+
+    it "reports the rejected accessory type even when action fields are present" do
+      Aeson.eitherDecode @SlackAccessory "{\"type\":\"static_select\",\"action_id\":\"select\"}"
+        `shouldBe` Left "Error in $: Unknown SlackAccessory type \"static_select\", must be one of ['button']"
+
+  describe "incoming Block Kit components" do
+    it "parses a message mention without a URL" do
+      Aeson.eitherDecode @RichItem "{\"type\":\"message_mention\",\"channel_id\":\"C123ABC456\",\"message_ts\":\"1720710212.123456\"}"
+        `shouldBe` Right (RichItemMessageMention (RichMessageMention (ConversationId "C123ABC456") "1720710212.123456" Nothing Nothing))
+
+    describe "rich-text list entries" do
+      let listWith entry =
+            object
+              [ "type" .= ("rich_text_list" :: Text)
+              , "style" .= ("bullet" :: Text)
+              , "elements" .= [entry]
+              ]
+          decodeList = parseEither (parseJSON @RichTextSectionItem) . listWith
+
+      for_ ["rich_text_list", "rich_text_quote", "rich_text_preformatted", "text", "future_container"] \(kind :: Text) ->
+        it ("rejects a " <> unpack kind <> " as a list entry") do
+          decodeList
+            (object ["type" .= kind, "elements" .= ([] :: [Aeson.Value]), "style" .= ("bullet" :: Text), "text" .= ("inline" :: Text)])
+            `shouldSatisfy` isLeft
+
+      it "requires the section type tag" do
+        decodeList (object ["elements" .= ([] :: [Aeson.Value])]) `shouldSatisfy` isLeft
+
+      it "requires the section contents" do
+        decodeList (object ["type" .= ("rich_text_section" :: Text)]) `shouldSatisfy` isLeft
+
+      it "preserves unknown inline items inside a section" do
+        let inlineItem = object ["type" .= ("future_inline" :: Text), "text" .= ("preserved" :: Text)]
+        decodeList (object ["type" .= ("rich_text_section" :: Text), "elements" .= [inlineItem]])
+          `shouldBe` Right (RichTextSectionItemList [RichTextSection [RichItemOther "future_inline" inlineItem]])
+
   let
     aSlackAccessory = SlackButtonAccessory aSlackAction
     aSlackAction = SlackAction
diff --git a/tests/Web/Slack/Experimental/Events/TypesSpec.hs b/tests/Web/Slack/Experimental/Events/TypesSpec.hs
--- a/tests/Web/Slack/Experimental/Events/TypesSpec.hs
+++ b/tests/Web/Slack/Experimental/Events/TypesSpec.hs
@@ -12,7 +12,9 @@
         (oneGoldenTestDecode @SlackWebhookEvent)
         [ "messageExample"
         , "messageChange"
+        , "message_deleted"
         , "message_rich_text"
+        , "message_rich_text_containers"
         , "message_file_share"
         , "message_file_share_slack_connect"
         , "link"
@@ -22,6 +24,8 @@
         , "messageIm"
         , "slackbotIm"
         , "channel_left"
+        , "channel_shared"
+        , "channel_unshared"
         , "share_without_message"
         , "share_with_message"
         , "circleci"
diff --git a/tests/Web/Slack/UserSpec.hs b/tests/Web/Slack/UserSpec.hs
new file mode 100644
--- /dev/null
+++ b/tests/Web/Slack/UserSpec.hs
@@ -0,0 +1,13 @@
+module Web.Slack.UserSpec (spec) where
+
+import JSONGolden
+import TestImport
+import Web.Slack.User (ListRsp)
+
+-- Fixture modeled on the example response at
+-- https://api.slack.com/methods/users.list#examples
+spec :: Spec
+spec = describe "User methods" do
+  describe "users.list" do
+    describe "Response FromJSON" do
+      mapM_ (oneGoldenTestDecode @ListRsp) ["with_bots"]
diff --git a/tests/golden/SlackWebhookEvent/botMessage.golden b/tests/golden/SlackWebhookEvent/botMessage.golden
--- a/tests/golden/SlackWebhookEvent/botMessage.golden
+++ b/tests/golden/SlackWebhookEvent/botMessage.golden
@@ -16,13 +16,15 @@
                             ( NonEmptyText "FVI" )
                         , elements =
                             [ RichTextSectionItemRichText
-                                [ RichItemText "TEST"
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                ]
+                                ( RichTextSection
+                                    [ RichItemText "TEST"
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    ]
+                                )
                             ]
                         }
                     ]
diff --git a/tests/golden/SlackWebhookEvent/channel_shared.golden b/tests/golden/SlackWebhookEvent/channel_shared.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/channel_shared.golden
@@ -0,0 +1,21 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev044RKJHB8W" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1664827321
+            , systemNanoseconds = 0
+            }
+        , event = EventChannelShared
+            ( ChannelSharedEvent
+                { connectedTeamId = TeamId
+                    { unTeamId = "E163Q94DX" }
+                , channel = ConversationId
+                    { unConversationId = "C123ABC456" }
+                , eventTs = "1561064063.001100"
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/channel_shared.json b/tests/golden/SlackWebhookEvent/channel_shared.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/channel_shared.json
@@ -0,0 +1,24 @@
+{
+  "token": "aaaa",
+  "team_id": "T043DB835ML",
+  "api_app_id": "A0442TUPHGR",
+  "event": {
+    "type": "channel_shared",
+    "connected_team_id": "E163Q94DX",
+    "channel": "C123ABC456",
+    "event_ts": "1561064063.001100"
+  },
+  "type": "event_callback",
+  "event_id": "Ev044RKJHB8W",
+  "event_time": 1664827321,
+  "authorizations": [
+    {
+      "enterprise_id": null,
+      "team_id": "T043DB835ML",
+      "user_id": "U0442US8QGH",
+      "is_bot": false,
+      "is_enterprise_install": false
+    }
+  ],
+  "is_ext_shared_channel": true
+}
diff --git a/tests/golden/SlackWebhookEvent/channel_unshared.golden b/tests/golden/SlackWebhookEvent/channel_unshared.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/channel_unshared.golden
@@ -0,0 +1,22 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev044RKJHB8W" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1664827321
+            , systemNanoseconds = 0
+            }
+        , event = EventChannelUnshared
+            ( ChannelUnsharedEvent
+                { previouslyConnectedTeamId = TeamId
+                    { unTeamId = "E163Q94DX" }
+                , channel = ConversationId
+                    { unConversationId = "C123ABC456" }
+                , isExtShared = False
+                , eventTs = "1561064063.001100"
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/channel_unshared.json b/tests/golden/SlackWebhookEvent/channel_unshared.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/channel_unshared.json
@@ -0,0 +1,25 @@
+{
+  "token": "aaaa",
+  "team_id": "T043DB835ML",
+  "api_app_id": "A0442TUPHGR",
+  "event": {
+    "type": "channel_unshared",
+    "previously_connected_team_id": "E163Q94DX",
+    "channel": "C123ABC456",
+    "is_ext_shared": false,
+    "event_ts": "1561064063.001100"
+  },
+  "type": "event_callback",
+  "event_id": "Ev044RKJHB8W",
+  "event_time": 1664827321,
+  "authorizations": [
+    {
+      "enterprise_id": null,
+      "team_id": "T043DB835ML",
+      "user_id": "U0442US8QGH",
+      "is_bot": false,
+      "is_enterprise_install": false
+    }
+  ],
+  "is_ext_shared_channel": false
+}
diff --git a/tests/golden/SlackWebhookEvent/forwarded_message.golden b/tests/golden/SlackWebhookEvent/forwarded_message.golden
--- a/tests/golden/SlackWebhookEvent/forwarded_message.golden
+++ b/tests/golden/SlackWebhookEvent/forwarded_message.golden
@@ -57,13 +57,15 @@
                                                         ( NonEmptyText "nXUog" )
                                                     , elements =
                                                         [ RichTextSectionItemRichText
-                                                            [ RichItemText "123"
-                                                                ( RichStyle
-                                                                    { rsBold = False
-                                                                    , rsItalic = False
-                                                                    }
-                                                                )
-                                                            ]
+                                                            ( RichTextSection
+                                                                [ RichItemText "123"
+                                                                    ( RichStyle
+                                                                        { rsBold = False
+                                                                        , rsItalic = False
+                                                                        }
+                                                                    )
+                                                                ]
+                                                            )
                                                         ]
                                                     }
                                                 ]
diff --git a/tests/golden/SlackWebhookEvent/link.golden b/tests/golden/SlackWebhookEvent/link.golden
--- a/tests/golden/SlackWebhookEvent/link.golden
+++ b/tests/golden/SlackWebhookEvent/link.golden
@@ -16,17 +16,19 @@
                             ( NonEmptyText "MEdM" )
                         , elements =
                             [ RichTextSectionItemRichText
-                                [ RichItemLink
-                                    ( RichLinkAttrs
-                                        { style = RichStyle
-                                            { rsBold = False
-                                            , rsItalic = False
+                                ( RichTextSection
+                                    [ RichItemLink
+                                        ( RichLinkAttrs
+                                            { style = RichStyle
+                                                { rsBold = False
+                                                , rsItalic = False
+                                                }
+                                            , url = "https://jadeapptesting.slack.com/archives/C043YJGBY49/p1663961604007869"
+                                            , text = Nothing
                                             }
-                                        , url = "https://jadeapptesting.slack.com/archives/C043YJGBY49/p1663961604007869"
-                                        , text = Nothing
-                                        }
-                                    )
-                                ]
+                                        )
+                                    ]
+                                )
                             ]
                         }
                     ]
diff --git a/tests/golden/SlackWebhookEvent/messageExample.golden b/tests/golden/SlackWebhookEvent/messageExample.golden
--- a/tests/golden/SlackWebhookEvent/messageExample.golden
+++ b/tests/golden/SlackWebhookEvent/messageExample.golden
@@ -16,13 +16,15 @@
                             ( NonEmptyText "u6n" )
                         , elements =
                             [ RichTextSectionItemRichText
-                                [ RichItemText "dgsfklsdgf"
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                ]
+                                ( RichTextSection
+                                    [ RichItemText "dgsfklsdgf"
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    ]
+                                )
                             ]
                         }
                     ]
diff --git a/tests/golden/SlackWebhookEvent/messageIm.golden b/tests/golden/SlackWebhookEvent/messageIm.golden
--- a/tests/golden/SlackWebhookEvent/messageIm.golden
+++ b/tests/golden/SlackWebhookEvent/messageIm.golden
@@ -16,13 +16,15 @@
                             ( NonEmptyText "LSo" )
                         , elements =
                             [ RichTextSectionItemRichText
-                                [ RichItemText "test"
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                ]
+                                ( RichTextSection
+                                    [ RichItemText "test"
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    ]
+                                )
                             ]
                         }
                     ]
diff --git a/tests/golden/SlackWebhookEvent/message_deleted.golden b/tests/golden/SlackWebhookEvent/message_deleted.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/message_deleted.golden
@@ -0,0 +1,20 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev043QRVT9FE" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1663969383
+            , systemNanoseconds = 0
+            }
+        , event = EventMessageDeleted
+            ( MessageDeletedEvent
+                { channel = ConversationId
+                    { unConversationId = "C043YJGBY49" }
+                , ts = "1663969383.001500"
+                , deletedTs = "1663966382.046509"
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/message_deleted.json b/tests/golden/SlackWebhookEvent/message_deleted.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/message_deleted.json
@@ -0,0 +1,37 @@
+{
+  "token": "aaaa",
+  "team_id": "T043DB835ML",
+  "api_app_id": "A0442TUPHGR",
+  "event": {
+    "type": "message",
+    "subtype": "message_deleted",
+    "hidden": true,
+    "channel": "C043YJGBY49",
+    "previous_message": {
+      "client_msg_id": "de349a9f-62a4-4293-b64d-701a1f566e8a",
+      "type": "message",
+      "text": "This message will be deleted",
+      "user": "U043H11ES4V",
+      "ts": "1663966382.046509",
+      "team": "T043DB835ML"
+    },
+    "deleted_ts": "1663966382.046509",
+    "ts": "1663969383.001500",
+    "event_ts": "1663969383.001500",
+    "channel_type": "channel"
+  },
+  "type": "event_callback",
+  "event_id": "Ev043QRVT9FE",
+  "event_time": 1663969383,
+  "authorizations": [
+    {
+      "enterprise_id": null,
+      "team_id": "T043DB835ML",
+      "user_id": "U0442US8QGH",
+      "is_bot": true,
+      "is_enterprise_install": false
+    }
+  ],
+  "is_ext_shared_channel": false,
+  "event_context": "aaaa"
+}
diff --git a/tests/golden/SlackWebhookEvent/message_file_share.golden b/tests/golden/SlackWebhookEvent/message_file_share.golden
--- a/tests/golden/SlackWebhookEvent/message_file_share.golden
+++ b/tests/golden/SlackWebhookEvent/message_file_share.golden
@@ -16,13 +16,15 @@
                             ( NonEmptyText "MeAN" )
                         , elements =
                             [ RichTextSectionItemRichText
-                                [ RichItemText "message message message"
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                ]
+                                ( RichTextSection
+                                    [ RichItemText "message message message"
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    ]
+                                )
                             ]
                         }
                     ]
diff --git a/tests/golden/SlackWebhookEvent/message_rich_text.golden b/tests/golden/SlackWebhookEvent/message_rich_text.golden
--- a/tests/golden/SlackWebhookEvent/message_rich_text.golden
+++ b/tests/golden/SlackWebhookEvent/message_rich_text.golden
@@ -16,58 +16,60 @@
                             ( NonEmptyText "6r5Zo" )
                         , elements =
                             [ RichTextSectionItemRichText
-                                [ RichItemChannel
-                                    ( ConversationId
-                                        { unConversationId = "C043YJGBY49" }
-                                    )
-                                , RichItemText " "
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                , RichItemEmoji
-                                    ( Emoji
-                                        { unEmoji = "cat" }
-                                    )
-                                , RichItemText " "
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                , RichItemUser
-                                    ( UserId
-                                        { unUserId = "U043H11ES4V" }
-                                    )
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                , RichItemText " "
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                , RichItemLink
-                                    ( RichLinkAttrs
-                                        { style = RichStyle
+                                ( RichTextSection
+                                    [ RichItemChannel
+                                        ( ConversationId
+                                            { unConversationId = "C043YJGBY49" }
+                                        )
+                                    , RichItemText " "
+                                        ( RichStyle
                                             { rsBold = False
                                             , rsItalic = False
                                             }
-                                        , url = "https://google.com"
-                                        , text = Nothing
-                                        }
-                                    )
-                                , RichItemText " text text text"
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                ]
+                                        )
+                                    , RichItemEmoji
+                                        ( Emoji
+                                            { unEmoji = "cat" }
+                                        )
+                                    , RichItemText " "
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    , RichItemUser
+                                        ( UserId
+                                            { unUserId = "U043H11ES4V" }
+                                        )
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    , RichItemText " "
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    , RichItemLink
+                                        ( RichLinkAttrs
+                                            { style = RichStyle
+                                                { rsBold = False
+                                                , rsItalic = False
+                                                }
+                                            , url = "https://google.com"
+                                            , text = Nothing
+                                            }
+                                        )
+                                    , RichItemText " text text text"
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    ]
+                                )
                             ]
                         }
                     ]
diff --git a/tests/golden/SlackWebhookEvent/message_rich_text_containers.golden b/tests/golden/SlackWebhookEvent/message_rich_text_containers.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/message_rich_text_containers.golden
@@ -0,0 +1,91 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "EvRichTextContainers" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1720710300
+            , systemNanoseconds = 0
+            }
+        , event = EventMessage
+            ( MessageEvent
+                { blocks = Just
+                    [ RichText
+                        { blockId = Nothing
+                        , elements =
+                            [ RichTextSectionItemList
+                                [ RichTextSection
+                                    [ RichItemMessageMention
+                                        ( RichMessageMention
+                                            { rmmChannelId = ConversationId
+                                                { unConversationId = "C123ABC456" }
+                                            , rmmMessageTs = "1720710212.123456"
+                                            , rmmThreadTs = Nothing
+                                            , rmmUrl = Nothing
+                                            }
+                                        )
+                                    ]
+                                , RichTextSection
+                                    [ RichItemLink
+                                        ( RichLinkAttrs
+                                            { style = RichStyle
+                                                { rsBold = False
+                                                , rsItalic = False
+                                                }
+                                            , url = "https://example.com/list-item"
+                                            , text = Nothing
+                                            }
+                                        )
+                                    ]
+                                ]
+                            , RichTextSectionItemQuote
+                                [ RichItemMessageMention
+                                    ( RichMessageMention
+                                        { rmmChannelId = ConversationId
+                                            { unConversationId = "C123ABC456" }
+                                        , rmmMessageTs = "1720710250.012345"
+                                        , rmmThreadTs = Nothing
+                                        , rmmUrl = Nothing
+                                        }
+                                    )
+                                ]
+                            , RichTextSectionItemPreformatted
+                                [ RichItemText "See the documentation:
+                                  "
+                                    ( RichStyle
+                                        { rsBold = False
+                                        , rsItalic = False
+                                        }
+                                    )
+                                , RichItemLink
+                                    ( RichLinkAttrs
+                                        { style = RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        , url = "https://example.com/code-reference"
+                                        , text = Nothing
+                                        }
+                                    )
+                                ]
+                            ]
+                        }
+                    ]
+                , channel = ConversationId
+                    { unConversationId = "C045V0VJT16" }
+                , text = "References in a list, a quote, and a code block"
+                , channelType = Channel
+                , files = Nothing
+                , user = UserId
+                    { unUserId = "U043H11ES4V" }
+                , ts = "1720710300.654321"
+                , threadTs = Nothing
+                , appId = Nothing
+                , botId = Nothing
+                , botProfile = Nothing
+                , attachments = Nothing
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/message_rich_text_containers.json b/tests/golden/SlackWebhookEvent/message_rich_text_containers.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/message_rich_text_containers.json
@@ -0,0 +1,73 @@
+{
+  "type": "event_callback",
+  "team_id": "T043DB835ML",
+  "event_id": "EvRichTextContainers",
+  "event_time": 1720710300,
+  "event": {
+    "type": "message",
+    "channel": "C045V0VJT16",
+    "channel_type": "channel",
+    "user": "U043H11ES4V",
+    "ts": "1720710300.654321",
+    "text": "References in a list, a quote, and a code block",
+    "blocks": [
+      {
+        "type": "rich_text",
+        "elements": [
+          {
+            "type": "rich_text_list",
+            "style": "bullet",
+            "indent": 0,
+            "elements": [
+              {
+                "type": "rich_text_section",
+                "elements": [
+                  {
+                    "type": "message_mention",
+                    "channel_id": "C123ABC456",
+                    "message_ts": "1720710212.123456"
+                  }
+                ]
+              },
+              {
+                "type": "rich_text_section",
+                "elements": [
+                  {
+                    "type": "link",
+                    "url": "https://example.com/list-item"
+                  }
+                ]
+              }
+            ]
+          },
+          {
+            "type": "rich_text_quote",
+            "border": 1,
+            "elements": [
+              {
+                "type": "message_mention",
+                "channel_id": "C123ABC456",
+                "message_ts": "1720710250.012345"
+              }
+            ]
+          },
+          {
+            "type": "rich_text_preformatted",
+            "language": "text",
+            "border": 0,
+            "elements": [
+              {
+                "type": "text",
+                "text": "See the documentation:\n"
+              },
+              {
+                "type": "link",
+                "url": "https://example.com/code-reference"
+              }
+            ]
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/tests/golden/SlackWebhookEvent/message_subtype_bot_message.golden b/tests/golden/SlackWebhookEvent/message_subtype_bot_message.golden
--- a/tests/golden/SlackWebhookEvent/message_subtype_bot_message.golden
+++ b/tests/golden/SlackWebhookEvent/message_subtype_bot_message.golden
@@ -16,17 +16,19 @@
                             ( NonEmptyText "nmh" )
                         , elements =
                             [ RichTextSectionItemRichText
-                                [ RichItemLink
-                                    ( RichLinkAttrs
-                                        { style = RichStyle
-                                            { rsBold = False
-                                            , rsItalic = False
+                                ( RichTextSection
+                                    [ RichItemLink
+                                        ( RichLinkAttrs
+                                            { style = RichStyle
+                                                { rsBold = False
+                                                , rsItalic = False
+                                                }
+                                            , url = "https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724954997876929"
+                                            , text = Nothing
                                             }
-                                        , url = "https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724954997876929"
-                                        , text = Nothing
-                                        }
-                                    )
-                                ]
+                                        )
+                                    ]
+                                )
                             ]
                         }
                     ]
diff --git a/tests/golden/SlackWebhookEvent/share_with_message.golden b/tests/golden/SlackWebhookEvent/share_with_message.golden
--- a/tests/golden/SlackWebhookEvent/share_with_message.golden
+++ b/tests/golden/SlackWebhookEvent/share_with_message.golden
@@ -16,13 +16,15 @@
                             ( NonEmptyText "Yyg6K" )
                         , elements =
                             [ RichTextSectionItemRichText
-                                [ RichItemText "hello check that out!"
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                ]
+                                ( RichTextSection
+                                    [ RichItemText "hello check that out!"
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    ]
+                                )
                             ]
                         }
                     ]
@@ -72,13 +74,15 @@
                                                         ( NonEmptyText "BXn1o" )
                                                     , elements =
                                                         [ RichTextSectionItemRichText
-                                                            [ RichItemText "this will be shared with a message"
-                                                                ( RichStyle
-                                                                    { rsBold = False
-                                                                    , rsItalic = False
-                                                                    }
-                                                                )
-                                                            ]
+                                                            ( RichTextSection
+                                                                [ RichItemText "this will be shared with a message"
+                                                                    ( RichStyle
+                                                                        { rsBold = False
+                                                                        , rsItalic = False
+                                                                        }
+                                                                    )
+                                                                ]
+                                                            )
                                                         ]
                                                     }
                                                 ]
diff --git a/tests/golden/SlackWebhookEvent/share_without_message.golden b/tests/golden/SlackWebhookEvent/share_without_message.golden
--- a/tests/golden/SlackWebhookEvent/share_without_message.golden
+++ b/tests/golden/SlackWebhookEvent/share_without_message.golden
@@ -57,13 +57,15 @@
                                                         ( NonEmptyText "TNHa4" )
                                                     , elements =
                                                         [ RichTextSectionItemRichText
-                                                            [ RichItemText "blahblahblahblahblah"
-                                                                ( RichStyle
-                                                                    { rsBold = False
-                                                                    , rsItalic = False
-                                                                    }
-                                                                )
-                                                            ]
+                                                            ( RichTextSection
+                                                                [ RichItemText "blahblahblahblahblah"
+                                                                    ( RichStyle
+                                                                        { rsBold = False
+                                                                        , rsItalic = False
+                                                                        }
+                                                                    )
+                                                                ]
+                                                            )
                                                         ]
                                                     }
                                                 ]
diff --git a/tests/golden/SlackWebhookEvent/slackbotIm.golden b/tests/golden/SlackWebhookEvent/slackbotIm.golden
--- a/tests/golden/SlackWebhookEvent/slackbotIm.golden
+++ b/tests/golden/SlackWebhookEvent/slackbotIm.golden
@@ -16,22 +16,24 @@
                             ( NonEmptyText "ZRe" )
                         , elements =
                             [ RichTextSectionItemRichText
-                                [ RichItemText "You have been removed from #testing-slack-app by "
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                , RichItemUser
-                                    ( UserId
-                                        { unUserId = "U043H11ES4V" }
-                                    )
-                                    ( RichStyle
-                                        { rsBold = False
-                                        , rsItalic = False
-                                        }
-                                    )
-                                ]
+                                ( RichTextSection
+                                    [ RichItemText "You have been removed from #testing-slack-app by "
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    , RichItemUser
+                                        ( UserId
+                                            { unUserId = "U043H11ES4V" }
+                                        )
+                                        ( RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        )
+                                    ]
+                                )
                             ]
                         }
                     ]
