Pre-FEP: Quote posts, quote policies and quote controls

to some extent the naming scheme of the term doesn’t matter as much as the IRI it expands to (https://misskey-hub.net/ns#_misskey_quote) or as much as the fact that the same term is broadly used. i understand it isn’t camelCase but it is at least properly namespaced.

_misskey_quote is supported by at least Misskey, all Misskey forks, and Threads. as:quoteUrl seems to have been picked by Pleroma and its forks. i can’t say with 100% certainty but i am pretty sure _misskey_quote is more widely supported on both the producing and consuming side.


aside on semantics

i’m not entirely sure what the exact semantics of a “misskey quote” are but it seems to match what mastodon wants out of “quote posts”, which seems to align vaguely with how twitter conceptualized “quote tweets”, although over there they look something like this in the v2 API:

    "referenced_tweets": [
      {
        "type": "quoted",
        "id": "1327011423252144128"
      }
    ],

and their v1.1 API looks like this:

{
  // ...
  "text": "To make room for more expression, we will now count all emojis as equal—including those with gender‍‍‍ and skin t… https://t.co/MkGjXf9aXm",
  "truncated": true,
  "entities": {
    // ...
    "urls": [
      {
        "url": "https://t.co/MkGjXf9aXm",
        "expanded_url": "https://twitter.com/i/web/status/1050118621198921728",
        "display_url": "twitter.com/i/web/status/1…",
        "indices": [
          117,
          140
        ]
      }
    ]
  },
  // ...
  "is_quote_status": false,
}

so it looks like the evolution started with “this is a link that is being quoted” and moved onto “this is the quoted status”.

back in Disambiguating various interpretations of a "quote" feature [pre-FEP] i explored the different aspects of what a “quote” could be – i continue to think that a great deal of “quote posts” most often fall into a bucket of “i am responding to the contents of the quoted post” (in which case, inReplyTo would be more appropriate and you could just render the replied-to post as a rich preview above):

above, we can see that “reply” and “quote” can be handled in exactly the same way – every reply can be handled like a quote, and it wouldn’t even be wrong. on the level of semantics, something is either a response or not. the prepend UI can be shown always. i’m still not sure what exactly a quote relation is supposed to mean, especially in the case where your post is not a response, and especially in a vacuum where twitter quote tweets never existed. over the past however-many years, people have tried using tag, attachment, and more bespoke properties to try to describe this relation. when i asked about this in infinite love ⴳ: "question mainly to proponents of quote posts, but…" - Mastodon the responses i got were all over the place, but the best i could say at the end was that “quoting” is roughly equivalent to “citing in full”. in the most generic sense, someone recommended from the CITO ontology http://purl.org/spar/cito/cites CiTO, the Citation Typing Ontology which has a lot of subproperties that are probably too granular for what most people care about – replies to, agrees with, even ridicules for those instances of quote dunks!

ultimately, the activity flow for requesting and obtaining authorization for a “quote” is independent of what a “quote” actually is. but insofar as anyone cares about “compatibility with existing representations”, _misskey_quote is the least compromised option here.

I honestly think the whole aside on semantics is out of topic. We already decided that quotes were not replies. Unlike replies they bring the discussion to a new audience, often with a different perspective or with a different point. And they can also be replies to other posts.

As for whether to use https://www.w3.org/ns/activitystreams#quoteUrl or https://misskey-hub.net/ns/#_misskey_quote, I have no strong preference, but I wish to avoid bikeshedding.

As far as I can see, Akkoma uses quoteUri and quoteUrl but not _misskey_quote, while Sharkey uses _misskey_quote, quoteUrl and quoteUri, and Misskey uses both _misskey_quote and quoteUrl.

the point of the aside is that _misskey_quote captures the semantics best, especially with intent to process it as mastodon intends to process it. i don’t want to bikeshed either, but _misskey_quote consumed by pleroma and its forks via the “common fixes” transformer i think? _misskey_quote is far and away more widely produced, while on the consuming side it’s probably about equal, with the only difference being which one is prioritized – misskey forks will prioritize the misskey property while pleroma will prioritize the false as: property. actually, pleroma says they got as:quoteUrl from misskey oddly enough: Quoting (!3921) · Merge requests · Pleroma / pleroma · GitLab and misskey likely got it from soapbox/rebased somehow if #113 - Quote posting - AkkomaGang/akkoma - Akkoma Development is correct. this is the link to gleason’s pr: Quote posts (!3616) · Merge requests · Pleroma / pleroma · GitLab and further digging shows Support for quoting posts from Soapbox/Rebased (pleroma fork) · Issue #9759 · misskey-dev/misskey · GitHub which eventually leads to AP引用でquoteUrlに対応 by mei23 · Pull Request #5632 · misskey-dev/misskey · GitHub which cites a mastodon 3.0 fork (?!) PR which wasn’t even merged: 引用機能 for v3.0.0 by wakin- · Pull Request #39 · wakin-/mastodon · GitHub

all signs point to as:quoteUrl being a historical accident, i guess? one that really probably should be put to rest, due to its incredibly poor conception/definition.

It looks like Akkoma may ingest _misskey_quote indeed, but does not output it. From a quick survey, as:quoteUrl seems more common than _misskey_quote but in the same ballpark, far ahead of everything else.

I am ok with using _misskey_quote. I’m also entertaining the idea of having a new https://w3id.org/fep/044f#quote that does not have any of this weirdness, and points to the spec, but it feels very xkcd-927. If we do go this way, we will have a non-normative section talking about as:quoteUrl, _misskey_quote and fedibird:quoteUri.

Mitra and Threads.

FEP-e232 has at least 9 implementations. All of them use FEP-e232 for quoting, even if specific relation type is not used, so it is one of the most common representations, if not the most common.

I display a quote for all object links where the target is a post. Other types of object links don’t exist, so I don’t see any reason to drop links based rel value.

If filtering based on rel is necessary for quote controls, your FEP can start with a recommendation for publishers to use a specific relation type, which later can be replaced with a MUST requirement.

Thanks! I think your statement might be slightly misleading. After a quick review, out of these 9 projects, I believe the following to be true:

  • Hollo supports and outputs _misskey_quote, quoteUrl, and _misskey_quote
  • Bridgy Fed understands and outputs quoteUrl and _misskey_quote
  • Threads outputs _misskey_quote
  • Pleroma outputs quoteUrl and quoteUri and handles _misskey_quote
  • Friendica understands quoteUrl, quoteUri, _misskey_quote and outputs quoteUrl
  • Iceshrimp.NET understands and outputs quoteUrl, quoteUri, and _misskey_quote
  • Mitra understands and outputs quoteUrl
  • FoundKey understands and outputs _misskey_quote and quoteUri
  • Streams understands quoteUrl, quoteUri and _misskey_quote but does not seem to output any of them (if I’ve looked correctly)

In short, except for Mitra, they all understand _misskey_quote; and except for Streams (if I’ve read it properly), they all output at least one of _misskey_quote or quoteUrl. So I don’t think the compatibility argument really is in favor of FEP-e232 (even though it’s not exactly a bad choice in that respect either)

Stepping aside from the compatibility argument, we have been told, and share the feeling that FEP-e232 kind of reinvents RDF within RDF. If we want to define a relation type, we may as well define a JSON-LD attribute in the first place, especially since we expect some specific behavior around quote posts. There is also the fact that in certain cases (e.g.) self-quotes, it might be useful to embed the quoted object rather than link to it, which is not possible with FEP-e232.

For these reasons, we are strongly considering using as:quoteUrl, _misskey_quote or a new https://w3id.org/fep/044f#quote attribute:

  • as:quoteUrl is one of the most commonly supported representations of quote posts; however it does refer to the object as Url, which is at odds with other definitions, and is not formally backed with anything, and there is no reason the object couldn’t be inlined; furthermore, it re-uses the ActivityStreams namespace without being defined there
  • _misskey_quote is also one of the most commonly supported representations of quote posts, and unlike as:quoteUrl, it does not re-use the ActivityStreams namespace, and does not imply the value is an URL; it does have an unusual naming scheme, and specifically mentions misskey, which is a bit awkward, but not a showstopper
  • quote would define exactly what we want, not implying an URL, and having a very descriptive name; it doesn’t clash with any commonly-used shorthand within another namespace, and namespacing it to the FEP would allow good discovery of the mechanisms we want to promote; it would not be compatible with any current implementation, however, but adding basic compatibility would be easy for any project currently implementing either of as:quoteUrl, _misskey_quote or quoteUri; we would also have a section on compatibility so that implementers are aware of these implementations and may chose to provide compatibility

I am only saying that other representations are not very far from FEP-e232 in terms of adoption. At the same time, FEP-e232 has several advantages:

  • Formally specified.
  • Multiple quotes per post are allowed.
  • Doesn’t make @context bigger.
  • Not limited to quoting, supports similar use cases.

What are the disadvantages? It is true that FEP-e232 doesn’t support embedding, but embedding prevents access control, so the only case where it might be useful is self-quoting, which constitutes a tiny fraction of all quote posts, so that hardly matters.

Multiple quotes per post are also technically allowed with the other properties, even if I haven’t seen any of that in the wild. It would also be technically allowed with our new proposal, though it is more awkward than the FEP-e232-based version of the proposal to match authorization stamps with quotes.

Not growing the @context bigger is not inherently an advantage, some of that can be shared, and cached. Whichever we end up going with, I was considering defining the used attributes in a FEP-044f-specific context that would be static and could be cached or even bundled with projects.

I feel like this is not limited to quoting because it is basically as open-ended as ActivityStreams and JSON-LD. We can make use of the open-ended nature of ActivityStreams and JSON-LD without pushing it down another layer.

Self-quoting is indeed only a tiny fraction of all quote posts, I’ll grant you that, but I also anticipate that to be an actual use case, especially with private posts, like private self-Announce is a use case supported by similar protocol features.

We have decided to move forward with a https://w3id.org/fep/044f#quote attribute, see #556 - fep-044f: Switch from FEP-e232 object links to bespoke `quote` and `quoteAuthorization` attributes - fediverse/fep - Codeberg.org

Kind of an aside from the current FEP, but we intended to use FEP-e232 for normal, non-quote links to posts and actors so that the server would not have to guess the type, and would allow clients to know those links are to be opened in-app, without attaching a preview or embedding anything in the post. Based on what you say, using FEP-e232 for this would have unintended consequences, would it not?

I don't think so. Previews could be useful regardless of the link type, and if they ever become a problem, it can be addressed quickly.

Ibis (federated wiki) may use FEP-e232 for links between articles (issue). If we learn that rendering previews for those links is confusing for users, we'll consider standardizing relation types.

I would like to reference this here: Should we ever think of a way how to embed ActivityPub objects into others (in the content)?

I kind of feel like the quotes described in FEP-044fConsent-respecting quote posts is just a special case of “Consent-respecting embeds in Objects” but with the constraints that

  1. There is only one embed
  2. The embeds within the object is not specified, rather a general relationship.

As I love all the work about the consent relating parts, and I think all of its vocabulary could be reused for embeds, I would propose generalizing the vocabulary identifiers, e.g. move from QuoteAuthorization toembedAuthorization.

EDIT: This change has now been merged

When writing FEP-044f, I had two reasons for the “author of the quote post is mentioned in the original post” rule of Verifying third-party quotes:

  1. consistency with the exception listed in GoToSocial’s interaction policies documentation, trying to not introduce inconsistent rules
  2. providing an “escape hatch”, being able to respond to accusations when someone mentions you directly

I now realize that the exception in GoToSocial’s interaction policies was specific to replies and did not apply to the other policies, so this point is in fact moot.

As for the second point, this can still be a useful “escape hatch”, but a more useful one is being able to reply, and this is still allowed by Mastodon (which does not support replies controls yet) and GoToSocial (which has an exception for this), so the usefulness of the exception is actually limited.

Also, while being hostilely quoted by someone you mentioned (for instance in a reply) is a much lower risk than being quoted by random people, it is still a risk that could be avoided entirely without that exception.

Furthermore, we now realize that this exception causes a lot of unclear messaging and UX complexities, such as the inability to revoke some quotes but not others.

Therefore, we think there are more reasons to remove this exception than to keep it, even if it’s already implemented in Mastodon (only verification implementation I’m aware of) and has been in the FEP draft for a while now.

See #660 - fep-044f: Remove exception allowing mentioned users to quote without approval - fediverse/fep - Codeberg.org

2 Likes

Now that Mastodon 4.5 is out and we’re starting to see its quote post interactions with Mastodon >=4.4 and other ActivityPub platforms with non-FEP-044f quotes, a question has arisen for me.

Mastodon 4.5 renders posts that advertise no quote policy whatsoever as non-quotable. Given the base assumption that FEP-044f quotes require approval, and implementations without a quote policy are presumably also incapable of issuing FEP-044f approval stamps, this seems like a sensible enough approach, at the cost of some social friction with AP implementations where quoting without approval is part of the generally accepted interaction model.

However, this makes me wonder if there should be some straightforward way for implementers to advertise (at the object level) that something can be freely quoted by FEP-044f implementations without individual approval. I’m thinking about simple public ActivityPub bots, software implementing FEP-b06c, or other contexts where free quoting may be desired, but managing approval stamps for each quote is overly cumbersome. This would also make this FEP much easier to implement for platforms which consider quoting without permission part of their social contract, in order to let people on FEP-044f platforms quote their posts.

Is this something that FEP-044f implementers would be open to? Or would you see it as undermining the purpose?

Mastodon 4.5 isn’t out yet. There’s just a bunch of servers running nightlies

1 Like

True! That’s my bad, I must be overly excited for quotes. :slightly_smiling_face:

1 Like

I’m not necessarily opposed to this. My only worry is that this would prevent authors from changing their mind or revoking a quote that has been made.

Yes, I think if I give implicit permission (let’s call it that for now, since “automatic permission” is already taken) to anyone to quote me without an approval stamp, the natural consequence would be that I lose the ability to revoke individual quotes. Is that inherently a problem? Implicit permission would likely only be granted by actors on software that doesn’t support quote permission revocations anyway.

We would need to think about the case where I author an interaction policy giving implicit quoting permission to, let’s say, https://example.com/luka, and then I later Update it to un-declare that permission. What would that mean for the quote posts (there might be multiple) which Luka has made that include my post? Changing the interaction policy on an existing object is established to be a valid action, so Luka can’t claim that my prior permission is irrevocable. Plus third-party observers can’t distinguish between a quote that used to be permitted and now is not, vs. one that was a forgery to begin with. So I think removing a quoting permission from the interaction policy would (should?) be treated the same way as revoking all individual quotes that are based on it, including if the permission was to as:Public.

Just to be clear, implicit permission isn’t really intended to be used by platforms that want to give their users control over who quotes them. I’m thinking about public bots, low-resource servers, and social platforms that want to make all their posts quotable by anyone, anywhere. From the discussions I’ve had with a few different implementers about this FEP, I worry that the mandatory authorization stamp management just to make something publicly quotable may already be hindering its adoption.

1 Like

I agree. My bots are very low tech. I can easily add the interactionPolicy JSON to them, but it is a bit of a pain to reply to every QuoteRequest

For “human” accounts, I completely get the need to have fine-grained control and to be able to revoke things. But for a bot which posts a link / image / whatever - I think it is overkill.

I’d like a permanent “Anyone can quote this” option.

Yes, that’s the crux of the issue for me. When we initially explored this we had a mix of the current approval flow and a list of stuff that would bypass the approval flow. But this makes the logic slightly more complex, and, more importantly, it means you can’t update the policy without invalidating existing quotes that were implicitly allowed. There is another subtle issue in which with the approval flow you know of everyone who has quoted you, so you have a good idea who to send information to if you want to update the policy or approve/revoke quotes, but if approval is implicit, the quoting end does not need to do that so you may be entirely unaware.

In the end, I’m not completely opposed to such a change, but I’m afraid this could make things more complex in the long run (even if it would indeed make things significantly simpler for specific use cases), and be too much of a foot-gunning hazard.

Meanwhile, I have started exploring the implementation space myself, and in the process of outfitting an ActivityPub bot with the ability to approve quotes, I realized the current schema can be satisfied stateless by handing out a customizable QuoteAuthorization.

The one I implemented includes the local and remote post IDs (which need to be referenced in the payload) as GET parameters in its own URL/ID, so anyone can fetch a QuoteAuthorization for any combination of quoted and quoting posts, including future ones, at any time. I still need to reply with an Accept to incoming QuoteRequests, but I don’t need to keep track of them otherwise. This approach largely solves my concerns and seems like a viable path for bot authors worried about the additional state management.

2 Likes