MSC4501: Social Media on Matrix - #4501
Conversation
There was a problem hiding this comment.
Implementation requirements:
- Chat client (backwards compatibility), or MSC mechanisms to prevent/discourage chat clients from encountering the data
- Social media client (first party compatibility, multiple)
There was a problem hiding this comment.
I have included a client that might cover both. A social media client added onto Element Web.
- Client (Haven Desktop):
- Bridge (matrix-appservice-activitypub):
- https://github.com/Haven-Organization/matrix-appservice-activitypub/blob/main/bridge/note_mirroring.py
- https://github.com/Haven-Organization/matrix-appservice-activitypub/blob/main/bridge/inbox_dispatch.py
- https://github.com/Haven-Organization/matrix-appservice-activitypub/blob/main/bridge/reaction_bridge.py
turt2live
left a comment
There was a problem hiding this comment.
Early review for early process requirements.
Spiritual successor to the abandoned MSC3639, defining room types for social media profiles (m.social.profile) and groups (m.social.group), a profile-discoverability field built on MSC4133, a post event type reusing m.room.message's schema, a single mechanism for reposts/boosts/ quote-posts, liking via standard m.reaction, room-membership-as-following, and a phased migration plan for treating m.room.message as an interchangeable stand-in for m.social.post during rollout.
Note that a repost's embedded body isn't tied to the referenced event's actual content at all, so a malicious repost could fabricate something the original author never said, not just resurface an edited/retracted statement.
A boost's outer body was empty/absent, which renders as a blank, confusing message bubble in any client without support for this proposal. Require a matrix.to/matrix: permalink to the reposted event instead, so non-compliant clients see an ordinary clickable link, and specify how a compliant client detects and re-renders that case.
a167973 to
69db24c
Compare
A repost previously only carried a copy of the original's body. Carry the whole content object instead (formatted_body, format, media fields like url/file/info, etc.), so a repost of a rich-formatted or media post renders the same as the original rather than degrading to a plain-text stand-in.
m.social.profile_user_id is a new room state event (fixed empty state_key, guaranteeing a room can only claim one owner at a time) that lets a profile room assert which Matrix user it belongs to, independent of its m.room.create creator (which can be a bridge or appservice bot rather than the real owner). Since it isn't one of the state events a default power_levels overrides, it inherits state_default (50, Moderator) rather than Admin-level protection; documented that gap and recommended an explicit override so moderators can't reassign a profile out from under its owner. Also carry the original post's sender and, optionally, displayname in m.social.repost_of, alongside its content, so a repost can credit the original author without a fetch to the original room.
m.social.repost_of.content_inline lets a boost point at the outer event's own content instead of duplicating a copy inside repost_of, for implementations (e.g. a federation bridge) that already build one copy of the reposted content as the event's own content. Also restructured the Reposting/Boosting/Quote Posting section around a mandatory/optional field list instead of prose, and made content optional but recommended, since omitting it means a client has to either fetch the live original (which can fail without permission or room membership) or fall back to a bare placeholder link.
Replace m.social.repost_of with m.social.relates_to, a generic cross-room reference block carrying a mandatory kind field (m.social.repost or m.social.reply) alongside the existing event_id/room_id/sender/content/content_inline/displayname fields. Reposts and cross-posted replies need the same shape for the same reason (rendering a cross-room reference without requiring room membership), so a shared block with a kind discriminator replaces what would otherwise be two near-identical mechanisms. Add a new use of kind: m.social.reply for cross-posting a reply into the replying user's own profile room, so it surfaces in followers' feeds the way replies show up on other social platforms' timelines, without disturbing the real in-thread reply, which still uses ordinary m.thread relations in the room it was sent in. This is aimed at implementations like a federation bridge that already need to mirror a reply both into its thread and into the replier's profile. Also recommend, but don't require, sending a rotating-arrows reaction on the referenced event alongside any repost/boost, so clients can compute repost counts via the same reaction-aggregation mechanism already used for likes. Updated Alternatives, Potential issues, Security considerations, and the Unstable prefix table to match, and trimmed the boost/quote-post detection prose.
Matches the field name Matrix's own m.relates_to already uses for the same purpose (naming a relationship type), which is also what an early independent implementation (matrix-appservice-activitypub) reached for unprompted, suggesting it is the more expected name. m.social.relates_to remains its own, distinctly named block though, not the real m.relates_to: added prose clarifying it borrows only the rel_type naming convention, not m.relates_to's server-side aggregation, bundling, or thread-rollup behavior.
Give quote-posting, reposting, and cross-posted replies their own sections instead of bold-lead subsections under Cross-room post references, and add an "Also known as" list under each (plus Liking) naming the equivalent action on other social media platforms. Standardize on "repost" as the canonical term in prose; "boost" and "retweet" now only appear inside the Reposts section's own "Also known as" list, not scattered through the rest of the document. Move repost counting (the recommended 🔁 reaction) into its own Repost counts section alongside Liking, rather than living inside the Reposts section. Drop the "m.social.like was considered and rejected" paragraph from Liking, since Alternatives already covers the same reasoning.
|
Did a little restructuring to the document to give each distinct flavor of event being proposed its own header. Also changed the language around reposts to be consistent throughout instead of interchangeably using other social media platforms' terminology. Other terms for these actions are now isolated in "Also Known As" sections under each type. No changes to any of the JSON schemas |
There was a problem hiding this comment.
Another question: How can this social media feed approach deal with per-post-visibility?
It is common for social media platforms to allow specifying whether a single post is publicly visible or only for followers. In the same way, replies could be public or only visible to the post author or even just visible to participants of the specific reply thread.
I don't see any mechanism in matrix currently to handle per-message overrides for readability of a message, so I guess this wouldn't work and therefore should probably be noted as a limitation.
Add m.social.body/m.social.formatted_body: optional content fields that let a compliant social client render a post differently from how the same m.room.message renders in an ordinary room timeline. Only valid alongside their non-m.social counterpart, and forbidden on m.social.post events, which have no non-compliant timeline to accommodate. Move Reposting with inline content here from the Reposts section, since content_inline exists for the same backwards-compatibility reason. Add a second example showing content_inline covers the whole outer content (attachments included, not just body text), and that m.social.body/formatted_body, when present, are what a compliant client should treat as the duplicated content's actual text rather than the raw body/formatted_body. Note the new section in the intro's summary bullet list.
|
Made the following changes:
No changes to any of the already-proposed types. |
- Rename proposal from "Rooms as Social Media Pages" to "Social Media on Matrix" - Reframe the MSC3639 relationship as additive rather than simplifying, and add a dedicated Comparison to MSC3639 section - Fix stale references treating MSC4133 as unmerged; it landed in Matrix 1.16 - Replace the Terminology section with an "Also known as" naming list under Posts
- Rename m.social.profile_room_id to m.social.profile_room, and change its
value from a bare room ID string to a {room_id, via} block, matching
m.space.child's own via convention, since room IDs aren't routable on
their own
- Add via as a RECOMMENDED field on m.social.relates_to for the same reason
- Update repost matrix.to/matrix: permalink examples to include ?via=
|
Added a place for |
- Add a table of contents after the intro - Nest Quote Posts, Reposts, and Cross-posted reply under Cross-room post references - Fold Client Backwards Compatibility into Handling m.room.message in social rooms: its two mechanisms (m.social.body/formatted_body, and reposting with inline content) are now subsections there instead of their own section
…mpatibility Nest the phased-rollout content under its own Handling m.room.message in social rooms subsection, alongside the other two backwards-compatibility mechanisms already there.
Rendered
A spiritual successor to MSC3639: Matrix for the social media use case (abandoned). This MSC provides the event/room/profile types, conventions, and guidelines to build a modern social media app on Matrix:
Signed off by: q havensoftware@zohomail.com
Implementations: