Disambiguating various interpretations of a "quote" feature [pre-FEP]

Broadly speaking, there are a lot of different, maybe mutually exclusive or incompatible ideas of what a “quote” is, or what it should do, or what it should look like, and so on. Many people, when asking for such a “quote” feature, are drawing inspiration from past features, perhaps more commonly the Twitter “quote tweet” or perhaps alternatively the forum-style “quote” as can be seen on this very Discourse forum. This pre-FEP aims to describe all possible approaches, as well as describing the pros and cons of each approach from both semantic and practical perspectives.

Implementation approaches

The quote reply

The semantic purpose of the inReplyTo is to denote that the current resource is “in reply to” or considered a response to the linked resource. Very often, a “quote” is semantically a response to the “quoted” resource. What actually makes it a “quote” is purely presentational or display-based; the “quoted” resource is embedded next to the “quote”. This embed can be placed below or above the current resource; because reading often happens top-to-bottom, a placement below the current resource allows the “quote” to act as framing for the “quoted”, while a placement above the current resource allows the “quoted” to provide a contextual preview for the “quote”.

Some implementations differentiate between “replies” and “normal posts”, while other implementations treat all posts the same regardless of whether they are in reply to anything or not. For example, at the time of writing this, Mastodon filters out “replies” from your timeline unless you follow the author of the post being replied to. Pleroma does no such filtering. Akkoma and Misskey make it a user choice. These are once again presentational choices, stemming from implementation-specific UX choices. For an AS2 producer which makes such distinctions, it may be helpful to signal a further distinction between “replies” and “quote replies”; a “quote reply” could be shown in timelines always, or considered the same as a “normal post”. If, for example, Mastodon wanted to adopt this strategy, it could define an extension property like http://joinmastodon.org/ns#quoteReply which, if set to true, would treat the resource linked in inReplyTo as a “Mastodon quote post”, opting into the rendering and timeline-filtering behavior associated with such a concept. An AS2 consumer sharing Mastodon’s UX choices and aware of this property would interpret objects with toot:quoteReply = true as “Mastodon-style quote posts”. An AS2 consumer not sharing Mastodon’s UX choices can render the reply metadata as it wishes; it is possible to render all replies as “quote replies” by simply embedding a preview of the replied-to resource above the current resource.

The quote tag

The purpose of tag is to markup the natural-language properties of name, summary, and content. In particular, substrings of content are often associated with richer metadata. Most commonly, tags of type Mention are used to associate a specific substring following a microsyntax, @mention, with a specialized Link that is intended to denote a “mention”.[1] Following this logic, Mastodon’s implementation of ActivityPub defined extensions for https://www.w3.org/ns/activitystreams#Hashtag[2] and http://joinmastodon.org/ns#Emoji. The Hashtag type is used to associate the #hashtag microsyntax with a “hashtag”, which is a reference to some string. The Emoji type is used to associate an :emoji: microsyntax with a “custom emoji”, which is an inline image with a square aspect ratio and the same height as a single line of text. In each of these cases, the name of the tag denotes the microsyntax, and this substring of the (sometimes plain-textified and HTML-stripped)[3] content can be replaced with a richer entity. FEP-e232 follows this logic as well; “object links” are tagged as a Link (or subtype) with appropriate mediaType, and the name is used to denote any applicable microsyntax such as RE: <url>, especially coupled with the use of rel to specify the link relation.

It is possible to build on FEP-e232 by using “object links” with a link relation specifically denoting a “quote” relationship. Some software such as Foundkey uses the rel-value https://misskey-hub.net/ns#_misskey_quote to denote a “Misskey quote”, while also accepting http://fedibird.com/ns#quoteUri and https://www.w3.org/ns/activitystreams#quoteUrl as equivalent. All three of these IRIs have historically been used as properties to express the same or nearly-identical concept – a single “post” that will be embedded as a preview below yours, separately from what you are replying to, intended to send a notification to the author of the quoted post that they’ve been quoted. It is possible to define standardized semantics using an IRI as a property or as a type, e.g. a Quote type.

The quote boost

The purpose of a share (Announce) is to draw attention to, boost, or republish the referenced object. Functionally, when sent to the author of that object, the author can add the Announce activity to the shares collection on that object. This gets interpreted as a “boost” or “reblog” within most current implementations.[4]

It is possible to add content to your Announce activity; a generic presentation of activities can use the natural-language properties name, summary, and content along with actor type object in order to generate a representation of the activity.

Comparison and analysis

Quote replies (reply with adjacent contextual preview)

  • (+) The quote reply maintains the best semantics in cases where the author is responding to the quoted object. It also falls back to a regular reply where not understood.
  • (+) The quote reply can easily inherit from “reply controls”, which allow authors of objects to grant stamps of approval that offer proof for a given object’s presence in the replies collection.
  • (-) The quote reply is practically (but not theoretically) limited to one “quoted” resource per post. It is possible to reply to multiple objects, although it is not immediately clear how this should be rendered or presented; adding a “quote reply” boolean property would limit the “quote” presentation to an all-or-nothing case, and selecting only some linked resources to be rendered as “quotes” would best be served by one of the other approaches.

Quote tags (rich quotes embedded in content)

  • (+) Multiple quote tags would be supported.
  • (~) Semantics can be signaled with rel or with extension types, but it is important to avoid proliferation of similar or identical semantic IRIs.

Quote boosts (reshare with comment)

  • (~) Might be semantically appropriate, if the “sharing” aspect of the “quote post” is what you intended.
  • (-) Falls back to a normal boost, without displaying the added content at all.

Footnotes


  1. (The exact meaning of a “mention” is not entirely clear. AS2-Vocab ties the definition to the @mention microsyntax, but provides no additional guidance on its intended functionality or meaning. At minimum, there is the implication that the Mention might denote an actor or a user, and might generate some notification that the mentioned entity has been mentioned. Software such as Mastodon follows this interpretation and uses mentions to generate notifications, but also goes further and requires tags of type Mention in order to determine delivery and addressing. Addressing someone in to/cc without mentioning them will create a “silent mention”.) ↩︎

  2. (Mastodon defining as:Hashtag within the activitystreams namespace is technically lacking authority, as only the W3C SocialCG can adopt new terms into the activitystreams namespace or make modifications to the normative activitystreams context. In particular, as:Hashtag is an inline extension, and it is not defined in the normative context.) ↩︎

  3. It is unclear when, how, or if such sanitiziation or stripping of content will take place. Current implementations are not entirely consistent with what they put into name (or href) compared to what they put into content. ↩︎

  4. Some software implementations do not use Announce as a reshare activity, and instead use it for other purposes outside of a publishing context, such as wrapping and forwarding someone else’s activity. The intended specified mechanism for doing this is inbox forwarding. ↩︎

7 Likes

Good write-up. I wonder if there should be more emphasis on the functional aspect of the mechanism from the perspective of the end user. For instance social impact. E.g. right now I witness toxic dynamic of ‘de-facto quotes’ in the form of toots like:

Uninformed / misleading / abusive statement

Quoted text from someone’s toot.

https://example.org/someperson/the-toot-being-targeted

And then a whole thread where people vent on the toot and the person who wrote it. All while the person is totally unaware this happens, and cannot set things straight if they wished to. It is possible that the toxicity is dialed up a notch because of this quote discussion happening out of sight of OP.

Feature may emphasize informing the OP (“You were quoted” notification) and their control over quoting as requirements. The ‘Quote replies’ mechanism with its fallback stands out most favorably here.

2 Likes

this is something i’m very wary of and also something that i have seen for myself multiple times in multiple environments. ultimately i think the problem is not that someone is “unaware” of such breakout threads. sending a notification doesn’t actually make the toxic dynamics any less likely to happen. rather, the issue is in creating perverse incentives for the person who is presented with the “quote” button, and these stem from platform design decisions.

if you look at “quotes” in a forum setting, they tend to be a useful tool and it’s hard to imagine them being used for toxic purposes, right? probably the only thing you can do there is something subtle like picking and choosing which parts of a long post you respond to, and which ones you ignore. but the “quote” itself is not doing anything bad; indeed, it isn’t doing anything more than providing a rich embed of a fragment of text.

i’d say the most significant factor is the order in which the text is presented. forums tend to have the quote first, and your response below. twitter has your comment first. as i pointed out above:

the “framing” aspect of whatever comes first can be used to “poison the well”, a rhetorical practice in which information presented beforehand can negatively color your perception of information presented after it.

i personally think “quote replies” and “quote tags” as worth pursuing, with “quote replies” being the primary thing people mean when they say “quote post”, and “quote tags” being more useful in a forum setting.

3 Likes

Yes, I agree.

With “unaware” I meant the difference in dynamics when people know that quoting informs the OP, i.e.

  • “I can relatively safely say what I want behind someone’s back”

versus

  • “My quote toot will be seen by the OP and I can expect a rebuttal”

The real troll will like the rebuttal, as their taunt worked. But the ‘rapid-reaction misinformed’, the ‘vicious gossiper’ and the ‘conform-to-status-quo’ in an in-group, are at risk of being put on the spot and tarnishing their reputation. They better be a bit more accurate and nuanced in what they write.

Sometimes, when I “quote” something, I do, in fact, provide a summary. However, others times, as with the quote above, what I wish to have displayed is a fragment from the object that is linked to. The two are very distinct in that a “summary” would be written by me while a fragment or extract is written by the author of the quoted object. Given this, I suggest that it is somewhat misleading to refer to the annotation referencing the quoted object as a “summary.”

To clarify, I was talking about summary as a property of an object, and having some item in the tag array related to some substring of it. The “annotation referencing the quoted object” is not the summary.

Exploring “quote proofs”

The prior post explores various approaches to defining what is a “quote”, but one thing that was left out of the original post was any sort of consideration of how to “prove” any or all such definitions of a “quote”. More precisely, it is generally desirable to have some mechanism to seek and signal the consent of the quoted person for the quoted segment. In the case of quotes, there is no special collection for tracking quotes, so an approach like fep/fep/0391/fep-0391.md at main - fediverse/fep - Codeberg.org is not applicable here unless a) you limit yourself to quote replies or Announce-with-content, which inherit the same “proof” considerations as any other item in replies or shares, or b) you define exactly such a quotes special collection, and probably a corresponding semantic property quoteOf which works similarly to inReplyTo… assuming you can precisely define what it means to “quote” something, semantically speaking. But in any case, we have other approaches than simply trying to establish membership in a special collection.

Proving “quote tags”

A “quote tag” was defined previously as a rich tag entity that can be embedded in the rendered content by processing microsyntax in ways similar to other tag entities. Prior work on FEP-e232 uses a Link tag with the AS2/AP mediaType, but we can extend the semantics as previously described, either through the use of a rel link relation like the _misskey_quote one, or by defining something like a Quote type which may be a subtype of Link, intended to represent what is more or less a blockquote with probably a source or cite. This is mostly besides the point, though; the interesting question that I’d like to explore here is how to obtain and signal consent for such “quote tags”.

Using the preview property of Link?

A tangential extension to FEP-e232 would be to use the preview property on a Link in tag, signaling that the link is intended to have a rich preview. This is an alternative to fetching any/all links yourself and parsing for OpenGraph or meta tags in the HTML head (in the case of a Link where the mediaType is text/html or assumed to be so). A common problem this would address is the “thundering herd” issue where linking to something on the fediverse often triggers a lot of GET requests to the linked resource, within close temporal proximity of each other, to the point that it can cause unintentional service degradation for the linked resource’s provider if their service is not optimized to handle a large volume of requests within a short period of time (for example, by utilizing a static cache). However, it would create a new trust issue for anyone who wants to consume such a Link.preview. Exploring a credibility or reputation mechanism to discourage activity/object producers from lying about link previews is out of scope of this post, but it could be done.

Obtaining a previewProof

An extension property previewProof could exist directly on the Link/Quote tag. What this points to is left open, but it should in some way be associated with the preview.

Signing the preview directly or using a Verifiable Presentation

Or, the proof could instead be part of the preview itself. One way to do this is with Verifiable Presentations.

This data model comes with its own mechanisms for establishing proof. Some entity with a key defined as an assertionMethod could assert that it approves of the preview. (The VCDI stuff is also the foundation fep/fep/8b32/fep-8b32.md at main - fediverse/fep - Codeberg.org styled “data integrity proofs”, but they can be used in other ways as well.)

The generic way you’d obtain and use such a proof could be described as follows:

  • You send some authority some material to sign, as well as potentially supporting information on how you’re going to use the resulting signed material.
  • The authority sends back the signed material. This step could be subject to either an automatic action or a manual human-approved one.
  • You attach the signed material to your activity, where appropriate. You can now send your activity to your desired arbitrary audience, and any recipient can verify that the proof is valid for the signed material.

There is still a potential consideration for the lifetime of the proof, as well as revoking an earlier proof. For this, I point to the concept of a “credential status” from the VC Data Model:

Basically, you can link to an external “status” indicator, or some other external “revocation list”, by which you can detect when the signed material is no longer to be trusted.

Alternatively, you can establish a system where the Verifiable Presentation is fetched directly from the issuer of the associated credential.

The exact mechanics of these suggestions is left out of scope for now.

1 Like

Worth considering the “remix quote”. Tumblr style of taking the original toot including metadata, and appending additional information into a brand new toot.

that’s more of a “reply context” imo

Throwing a remix of this idea into the ring as well:

The quote activity

Instead of an Announce with content, we can define a new Activity type Quote that can be used similarly, but has different semantics. Whereas an Announce is defined like so:

Indicates that the actor is calling the target 's attention the object .

So instead of “calling for attention”, the Quote activity would instead be defined semantically as:

Quote
: Indicates that the actor is quoting the object verbatim in its entirety.

The “quote activity” might also instead be named something else to avoid potential conflicts with other shorthand terms. Something like Cite could also work. Alternatively, other disambiguated senses of the word may be represented in the noun form as a Quotation or Citation.

  • (~) No fallback. This could be either good or bad, depending on if you want a fallback or if you want the semantics to be respected.
  • (+) With the existence of a quotes collection (even if the items might be private), we can use its IRI as the target of an Add which acts as a stamp of inclusion in a parallel way to how one might signal an Add into the likes, shares, replies, context, etc collections.
  • (+) In theory supports one or multiple object references, but even if you limit the cardinality to 1, this at least “frees up” the inReplyTo property for cases where you might reply to one post while quoting a different post. It also remains possible to Quote an object while also declaring that your Quote is inReplyTo the same object.