-
-
Notifications
You must be signed in to change notification settings - Fork 351
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[protocol] Questions and remarks about Interaction Policies #3616
Comments
Adding a couple questions I thought about when the repository was locked for the holidays: Approval type swapAn attacker could obtain approval for one kind of interactions (e.g. liking a post) before swapping the activity and type with something else (e.g. a reply). That being said, this is a difficult issue to solve, as having the type hardcoded would not prevent e.g. swapping a reply with another one that has different contents. The only way to fully avoid that kind of things is to sign the accepted activity in the approval, but that comes with many drawbacks. Private collections in
|
Alright! Back from holidays, gonna have a crack at answering these questions now :) I'll start with the brief ones.
This one's covered here: https://docs.gotosocial.org/en/latest/federation/posts/#validating-presence-in-a-followers-following-collection Basically, in this case the interacter should wait for approval from the interactee before broadcasting the activity with the Accept URI attached, as there's no other way in the current setup for remotes to validate presence in a followers/following collection. We could implement some FEP or follower synchronization method for this in the future, maybe, but for now this was the simplest way of handling it.
Yeah it's definitely not watertight, indeed someone could swap the contents of an approved reply for something else. They can also do this using edits if they want to. In future we might want to encourage interacters to revalidate statuses or something by requesting a new Accept from the interactee, or having the interactee put a digest in the Accept activity so that remotes can check what's actually Accepted. Not sure yet.
Indeed we rely on in-mem caching and request throttling for this. The situation isn't much different from someone with lots of followers boosting a post. So far we haven't seen any issues with this but it's worth bearing in mind as Mastodon servers (which tend to have a lot more users + users with a lot more followers) also start to adopt interaction policies.
This is definitely open to changes :) I'm the one who wrote that part of the document, but afaik it's not really being used yet, GtS always just sends everything. I only added it for the sake of trying to eliminate undefined behavior. If you'd rather that leaving a policy out is equivalent to as:public then that could work as well, all good for us!
Yeah that's definitely a gap! If I remember rightly in the code we treat Reject as a revocation, and handle side effects appropriately but that's not mentioned in the document. This is something to ponder and something that should definitely be added.
I guess this is similar to revocation in that if you're changing to a more restrictive policy, we'll have to think about this one a bit more as it's quite tricky indeed, especially the point you raise about interactions that are implicitly permitted and therefore don't carry an Accept URI with them. One way of handling this, I suppose, would be for the interactee's server, when the policy changes, to send out Accepts to all interacters whose interactions were already implicitly accepted due to as:public, so that the Accept URIs could be added to those interactions at the moment the policy changes, allowing those interactions to remain. Alternatively, though this creates a lot more traffic, would be for the interactee to always generate + send out an Accept even for interactions that are permitted implicitly. A third (much less preferable) option would be for the interactee's server to send out Rejects to all interacters whose interactions would be rejected by the new policy, essentially "clearing" those interactions. I don't really like this though. When you close discussion on an issue or a forum or whatever, you don't wanna delete the history of the discussion :') At least, not usually.
I was toying with a similar idea, I think maybe we discussed this on the fedi or on discord at some point? I don't quite remember. Ideally I'd like to avoid introducing a new endpoint if possible, as it requires further protocol extensions. But maybe it will be necessary. Not sure!
Yeah! This is similar to something mentioned here: #3460 Basically I wanted to avoid introducing types like AcceptReply, RejectReply, AcceptLike, AcceptAnnounce etc etc as it's just a bloody mess when you consider all the different types of interactions you might want to accept or reject. But perhaps there's a neat way of hinting within an Accept or Reject exactly what you're Accepting or Rejecting. |
FYI our current work-in-progress draft for quote posts uses a top-level
Oops yeah, I missed it indeed. Fundamentally, your proposal does cover this. Maybe it can be worded a bit more clearly and call this out earlier, but maybe that's just a me problem!
It is a bit similar, but on first discovery you need two requests (post + interaction approval), and for every subsequent use you need a request, even if you know the original post. Which is definitely more than with boosts.
This one is a bit tricky, but what we think is:
I think it's actually not very similar to revocation, as you'd likely not want to automatically revoke existing approved interactions on policy change. This would be your third option, and I agree this is much less preferable. Your first option does make a lot of sense although it could create a big burst of traffic. Your second option would also make sense and that's actually what I would suggest (unless we're adding a new endpoint, see next point), making the policy entirely advisory, and the enforcement a separate concern.
The proposed flow, especially with “DO NOT DISTRIBUTE THE ACTIVITY FURTHER THAN THIS AT THIS POINT.”, is already a pretty big protocol extension. There's a not-completely-satisfactory way out of it by allowing I'm kind of in favor of introducing a new endpoint since it could streamline things quite a bit, but also I'm not sure how it would work with C2S yet.
I understand wanting to avoid adding those, although they are not more “expensive” from a compatibility viewpoint, and avoid potential confusion. We can probably use |
I suppose you could also flatten it to something like this: {
[ ... blah blah blah the rest of the Note ... ]
interactionPolicy: {
"canLikeAlways": [ "zero_or_more_uris_that_can_always_do_this" ],
"canLikeApprovalRequired": [ "zero_or_more_uris_that_require_approval_to_do_this" ],
[ ... blah blah blah the rest of the things in the same pattern ... ]
}
} But I wouldn't put things like
I'm very wary of this as I think it's going to introduce a much higher possibility of different implementers getting their wires crossed trying to remember what is implicitly permitted and what is implicitly not permitted. It also relies on and codifies social norms which I don't think should be relied on or codified. I think protocol extensions should try to stay neutral and technical where possible, ie., "if a key is omitted the interaction is always permitted" or "if a key is omitted the interaction is always forbidden" and not "if the Like key is omitted it's always permitted because likes are 'less of a big deal', if the Reply key is omitted it's always forbidden because replies are 'more of a big deal'" etc. Does that make sense?
I don't really agree with this: in my experience people often post things on followers-only not because they necessarily want to limit views to only their followers, but because they don't want stuff getting boosted all over the place and attracting attention outside their bubble. In that light, folks definitely recognize announcements as a form of interaction that they might want to limit.
Second option is fine then I think :) It also helps with distributing replies, which is a nice bonus.
Tbf it's always going to be advisory, we can't stop other implementations from doing whatever they want :P
I think this would definitely be enough to hint to the receiving instance about how they should handle the Accept. I'd be totally OK with adding this!
They might yeah, you never know. But afaik most other implementations use Accept to look at Follow (requests) only, I think. Prior to implementing interaction policies, GtS would just look for the target of an Accept in the database, and if it didn't find anything, would return 202 and do nothing else. I imagine that's what other implementations are already doing with the Accepts GtS is now sending out in response to interactions. I haven't heard of it causing any issues yet 🤞 |
Checking the keys of the root object is also not more complicated than checking the keys of
Oops, sorry, I thought something but wrote something else (edited the post afterwards): I meant it's established in the fediverse (as in, every implementation for years) that So it makes sense to me that in the absence of a I definitely think the ability to set a policy for announces can be useful.
It would still not be enough if we e.g. have something that is both in-reply-to and quoting the same post, and we want to distinguish the two abilities. This might sound very artificial, but being able to tell the two apart makes sense if you consider the ability to change a policy without invalidating previous interactions: it may not be possible to distinguish an adversary making double-use of an approval, and a legitimate use of e.g. quote before the quoted user changed their policy. |
Sure, but I meant the policy itself would never be used for verification, which would be a separate concern.
That makes sense, but also the established technical point is that the likes and replies do not require permission, that's the expectation for implementations that do not implement that extension, so codifying the opposite seems weird and unpractical compatibility-wise. But I understand your position, and, for instance, in Mastodon we do not plan on supporting quoting posts that do not advertise a policy, because quotes are new and existing posts are not. |
Right! I think I finally understand what you're getting at, my bad. So what you're saying is, when
Then you should assume that only followers can reply straight up, and the rest requires approval, but likes and boosts are implicitly approved, right? And then quote posting is special cased so that even though likes and boosts are implicitly approved, quote posts are not. Am I understanding that correctly? I think that would be more or less OK tbh. I think we'll end up differing here in that with GtS we'll probably always transmit the whole policy to make things explicit, but as long as we're working from the same assumptions it's not an issue for cross-compatibility. We'll just have to be very careful when writing this up to make things as clear as possible. |
Yes, that's what I meant. As for your example, I'd still remove the distinction between |
One issue I've been pointed out is that when canonicalizing a JSON-LD document, empty arrays just disappear, so this means with Mastodon's current signature scheme, we cannot assign different values between “missing property” and “empty array”… this is very troublesome. An ugly workaround could be to never leave those attributes empty, by always putting the actor's URI in there, since they are always implicitly allowed to interact with themselves. |
That's prettymuch what GtS does already :) viva ugliness! 🦥 |
Hi!
We are currently working on quote posts in Mastodon, and one essential feature we want is control by the quoted person on who can quote them. Given the similar purposes, we had a look into your Interaction Policy proposal (we are also interested in at least reply controls, but that's something we'll tackle later, and quote posts may be a good way to evaluate that approach in practice and at scale).
In doing so, we have encountered a few shortcomings, possible improvements or questions. I will try to summarize them.
Implicit policies
Our most immediate use case is to represent policies for quoting, which is not defined in your document, but a
canQuote
policy seems like a natural extension of your proposal.However, we would not immediately support interaction policies for the other kind of interactions, so it would make sense leaving them out, but according to your documentation, leaving a policy out is equivalent to outright denying interactions, which is not what we want to do.
I suppose we could have
as:Public
inalways
, but it slightly bloats the messages while kind of implying that we support those policies in any way, and it brings up the issue of changing the policy after the fact (this is expanded on later in another section).Revocation of previous approvals
One thing people tend to expect, and that we are intent on allowing wrt. quote posts in Mastodon, is revoking approval for an interaction (see Bluesky's functionality to “detach a quote”).
I suppose it could be done by occasionally re-checking the
approvedBy
activity or sending and forwardingReject
activities (with no guarantee they would reach everyone who processed the approval in the first place though), but this is not discussed at all in your documentation.Changing an existing policy for a more restrictive one
Say a post exists without a policy, or with an
"always": "https://www.w3.org/ns/activitystreams#Public"
policy, and gets some interactions.Because those interactions are immediately allowed by the
always
policy, they bypass the approval flow and do not carry anapprovedBy
attribute.Now, say the user has changed their mind (or the software they use has been updated to support policies) and do not want any more interactions without approval, specifying a more restrictive policy. From the user's perspective, this should not invalidate existing interactions.
However, already-issued interactions did not need and did not produce an approval activity, and do not refer to one in
approvedBy
, meaning that third-party servers cannot verify them.One idea that I had though I don't know how much sense it makes, is mandate that the approval activity, if it exists, can be dereferenced at a deterministic address that would be enough for the approval-granting server to evaluate and grant approval on the fly, e.g.: the authorization for a reply
https://reply.example.com/users/123/statuses/456
to a posthttps://origin.example.com/objects/1234
could be queried athttps://origin.example.com/objects/1234/interactions/reply?uri=https%31%2F%2Freply.example.com%2Fusers%2F123%2Fstatuses%2F456
(This would not mandate that this is the identifier of the approval, but that would also be possible)
Ambiguity of approvals
In your proposal, you re-use
Accept
andReject
to represent approval or rejection of an interaction, relying onactor
andobject
to identify the interaction.This works for your examples, but can be ambiguous. Indeed, consider a reply that is
inReplyTo
two different posts are more (this is typically not handled by microblogging software, and in particular not by Mastodon, but this is allowed by the specs and some software support it). How to handle a rejection or an acceptance then becomes ambiguous. Even moreso if multiple posts being replied to are from the same person.The issue rises in the context of quote posts as well: a quote post could be in reply to another post, and be subjected to two interaction policies of different kinds at once, a reply policy, and a quote policy, and you may want to react differently to a rejection from one or the other. For instance, in our design, a revoked quote approval would mean the quoting post still exists but the quote itself is replaced with a placeholder. But if we are quoting and replying to the same person and get a rejection (or an approval that gets retracted), it is not possible with your proposal to tell which interaction was denied.
Scaling
Your proposal requires every third-party server to fetch an approval for every interacted post, which can generate a lot of traffic if a post gets interacted with by a popular account.
I unfortunately do not have any idea how to improve that, except for the use of a short-lived inline signature to ease with the initial distribution, but it would still behave as badly if the interaction gets shared after the signature's expiry.
At least the approval document can get cached.
The text was updated successfully, but these errors were encountered: