How do we handle Groups (Reconciling FEP-400e and FEP-1b12)?

I think in order to reconcile FEP-400e and FEP-1b12 the following changes can be made:

  • Both FEP-400e and FEP-1b12 implementations: support FEP-7888 (context collection)
  • FEP-400e implementations: upgrade to Conversation Containers
  • FEP-1b12 implementations: add target property to Announce activity that points to context collection.

Activity types will still be different (Add vs Announce), but consuming implementations can easily accept both.

3 Likes

@silverpill@socialhub.activitypub.rocks Unless I'm reading this wrong, you're advocating that we should:

  1. Reduce the number of moving parts to 2 (400e bows out in favour of 171b)
  2. Encourage broader adoption of a resolvable context property (this would be the one differentiator that can be used as feature detection)
  3. Implementations should accept both Add and Announce activities as valid for appending to a resolvable context collection.

Let me know if I have that right, I'd like to discuss this at the upcoming ForumWG meeting Thursday.

2 Likes

My concern is about the continued usage of target in a way that is redundant with context and also not matching the semantic meaning of “target”.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://example.com/some-activity",
  "actor": "https://example.com/some-actor",
  "type": "Create",
  "object": {
    "content": "Hello world",
    "context": {
      "id": "https://example.com/some-conversation",
      "type": "OrderedCollection",
      "attributedTo": "https://example.com/some-moderators"
    },
    "target": {
      "id": "https://example.com/some-conversation",
      "type": "OrderedCollection",
      "attributedTo": "https://example.com/some-moderators"
    }
  },
  "to": "https://example.com/some-moderators"
}

From 400e:

Currently, there is no generic way to signify that an object was created as part of a collection and should only be considered in its context.

While [Activity Vocabulary] specifies target as a field with similar semantics in activities, it’s important to include it in objects themselves so any software that only sees the object without its enclosing Create activity, e.g. when following a link form another object or retrieving the object from a user-provided URI, unambiguously knows that it should only be considered in the context of its collection.

Emphasis mine, again. context is valid on objects and target is only valid on activities, plus target means something different – it’s the grammatical indirect object, which is not defined for Create as a verb. It would honestly make more sense to use to than to use target. (And in fact, this is one way a self-managing collection-actor could work, where the actor can Add items into itself as a Collection.)

There is also a possibility that a producer might produce an activity or object where context and target point to different collections. This would be really bad. I think we should not open the door to that possibility.


As for reconciling 7888 with 1b12, you can put context on the inner object (the “post” itself), and you can put audience wherever you please. So it’s possible to conform to both… although I still think that 1b12 makes too many assumptions that don’t hold up, like that the actor must always be a Group, and that it always sends an Announce wrapping an activity instead of wrapping the “post” object, and that the “first post” is a Page, and that all Group actors behave like this, etc. These are all fragile assumptions to make and can easily be broken (particularly the last one). But those can be ironed out over time.

The main change that 1b12 implementers should make is to detect the presence of context as representing a logically grouped “thread”, and to reduce reliance on inReplyTo chains.

I think the only change that 7888 implementations need to make is to consider the possibility of encountering objects that declare a local context without having been delivered to that context?

I guess when you put it like that, there’s not actually much of anything to “reconcile”, is there? The only practical implication of all this is that some actors will send out an Add (where the Add.target is the Add.object.context which indicates the thread, and the Add.object indicates the post to add to that thread) and some actors will send out an Announce (where the Announce.object.object.context indicates the thread, and the Announce.object.object indicates the post to add to that thread). Obviously I prefer the Add because it’s more explicit, but I guess you could send both an Add and an Announce to your followers… perhaps the 1b12 Group sends the Announce, while the context owner sends the Add. This is somewhat duplicative, but it’s less duplicative than the context/target thing mentioned above. I suppose it could also depend on whether you follow the 1b12 community (which sends an Announce), or if you follow the thread itself (which sends an Add).

3 Likes

Yes, that’s correct. I believe it is also important to make context a collection of activities, because reactions are part of a conversation too (I didn’t fully realize that until I added support for FEP-1b12 Announce(Like) and Announce(Dislike))

disagree that context should contain likes and dislikes. i think those should go in collections like likes or an extension-defined dislikes.

but also, context is agnostic to what it contains. this is why i was thinking of maybe defining new types to signal that the collection should contain “posts” (objects that have content) only, or if it can contain other non-“post” objects like Like/Announce/etc activities.

the main mechanism for deciding what goes in a context collection is more or less “whatever declares that context and gets delivered to / added by the authority”

Okay, so we have some disagreement here with respect to what a context contains. Perhaps my understanding was outdated, but I thought there was some limited discussion about outbox containing the full activity log, and the collection containing the post objects. That would satisfy both sides, if I am not mistaken.

Usually the conversation devolves into "what is an actor, anyway", but let's keep things on track today LOL

1 Like

So servers will need to make additional requests for every object in a context collection when backfilling a thread? This is quite inefficient.

The goal is 0 additional requests because every activity in collection is signed.

1 Like

i am in favor of having contexts contain “post” objects as you well know, and for making collections into actors that can be followed and can have outboxes. you’re not outdated or mistaken there :slight_smile:

the only missing bit is some signal to describe what a context collection contains, and if it is a collection-actor, then some signal to describe how it behaves.

specifically this where the new types could come in. very loosely i was toying with something like the following

for collections representing a conversation, we have the following attributes we could signal:

  • “this collection contains objects sharing the same context
  • “this collection contains objects that have text content

for actors representing a topic or community, we have the following behaviors we could signal:

  • “this actor announces any activity sent to it” (new style boost bots like 1b12)
  • “this actor announces the object of any Create sent to it” (old style boost bots like guppe)
  • “this actor adds any Create.object or activity it encounters with the same context to a context collection that it owns” (context manager)

maybe types aren’t the best way to signal all of these things, but it’s what we have available to us at the moment, barring the development of some kind of FEP to allow actors to signal which clients they have attached to them and how those clients behave.

at the very least, the collection subtypes make enough sense to consider for now… i might have to revisit the actor behaviors later, because if we just define types for every behavior then this could quickly lead to actors having more types than you know what to do with. also i think more precisely these behaviors are properties of the client attached to the actor, not the actor itself.

tldr if you want to distribute Likes and Dislikes and Announces as part of a context/conversation then i think the best we can do right now is have the author of the Like/Dislike/Announce consider putting context on those activities, and then it’d be up to the receiving context manager to decide whether they want to allow those contentless activities to be added to the context collection or not.

it’s only inefficient if you care about like/dislike/share counts. i am fundamentally disagreeing that those activities should be considered part of a conversation. it adds nothing to the conversation to just tell everyone “i like this” with zero additional input to the conversation. now, if you wanted to clarify and say “i like this because …” then maybe you actually are contributing to the conversation. you’d do that by putting content on your Like, which turns it into a “post”. (posts dont have to be Notes or Articles. activities can be considered “posts” if they have content.)

From an implementor point of view, I will say that if I receive a context and it contains the entire activity history, I will simply retrieve everything and normalize it down to the items that I do care about.

For example, a collection containing:

Create(Note), Like(Note), Announce(Note), EmojiReact(Note), Create(Note)

would be collapsed down to

Note, Like, Announce, (ignored), Note

Whereas a collection containing just the objects would not need collapsing (it'd just be Note, Note). Either way, it containing the entire history does not impede my ability to parse it.

Sure, I'd miss some of the activities around it, so that's a concern, but it's not a dealbreaker. That's why I'm on the fence about this one.

My personal opinion is that this could be a non-issue. If the verbiage on the FEP were amended so that it says:

The collection MAY contain complete activities (this includes Create, Update, Delete, Like, EmojiReact and other activities) OR simple objects.

I would have no problem with this, but I do not know if this is a problem for others.

@julian I'd lean towards activities, because it's a lot easier to remove data you don't care about, than to reinvent data that you do care about but never received.

@julian I'd lean towards activities, because it's a lot easier to remove data you don't care about, than to reinvent data that you do care about but never received.

You’d be missing activities regardless. If someone sends a Create Note with a context to the context manager, and I’m following the context and receive this activity, I might send a Like to the author of the Note but NOT to the context manager. In that case, the only way to obtain a complete view of the likes collection for that Note is to ask its authoritative origin. This is going to be something that happens a lot due to the messiness of fediverse implementations – you might have 3 Likes be delivered directly to the context manager, but 7 other Likes be delivered only to the author of the liked post. If you are only processing the context collection, then does the post in question have 3 likes, or 10?

1 Like

It's probably not going to be what some people want to hear, but some degree of lossiness is unavoidable.

All we can do is apply our best effort and set forward a straightforward recommendation that other implementors can consume and implement with minimal variance.

That's why I eschew esoteric and complex implementations when a simpler mechanic would suffice.

Duck typing can be used to identify activities. I’d prefer a cleaner solution, but not strongly opposed to this idea.

some degree of subjectivity is also unavoidable. this is why i was talking about the additional signals/types above, so that you can tell if a collection contains “posts” or if it also contains some additional “non-posts”. i don’t think everyone is going to agree 100% one way or the other on what exactly makes up a “conversation”.

I'll informally poll at the WG meeting Thursday for opinions. Results are of course non-binding.

I'm afraid that not only are we not going to agree, even if one option is recommended by decree, there will be implementors who refuse to adopt.

It seems evenly split right now.

While discussing what is contained in the context collection, I'd like to clarify what exactly is being Add'ed in 400e and (the upcoming) 171b, and whether that also coincides with the collection items.

That is, if a context collection contains only simple objects, then the assumption is that context owner will only federate an Add out for simple objects. Likewise if the collection contains activities, then I'd expect Add(Like(Note)) to come from that owner.

However, a quick re-reading of 400e suggests that only simply objects are federated out via Add. That would tip the scale a bit toward the context containing only objects.