FEP Convergence (400e, 7888, 171b/Conversation Containers, 76ea)

Related to the ForumWG topic of resolvable context collections, there are four FEPs that are currently in consideration:

  1. FEP-7888: Demystifying the context property
  2. FEP-400e: Publicly-appendable ActivityPub collections
  3. Draft FEP-171b: Conversation Containers, an evolution of Conversation Containers
  4. FEP-76ea: Conversation Threads

@silverpill@mitra.social made a suggestion last month to hopefully reduce the number of moving parts:

  • 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.

This takes FEP 400e out of the running (potentially). But the day after that last meeting, @evan@cosocial.ca put together FEP 76ea, and now we're back to three.

My concern is that all three FEPs (7888, 171b, and 76ea) all share these distinct qualities:

  • They establish a conversational context for a given object
  • They federate out an Add on collection addition. (76ea also sends Remove)
  • They contain some concept of a context owner (attributedTo)

They differ on the following qualities:

  • 7888/171b use context whereas 76ea uses a new property thr:thread
  • 171b specifies a new object type Context
  • Collection items:
    • 7888 sends objects in chronological order
    • 171b sends activities in chronological order
    • 76ea sends objects in reverse chronological order

In the lead up to the November WG meeting I'd like to address those differences. All three FEPs are in pre-draft or draft stages, and so I am hoping we can find some common ground and compromise.


Pinging interested parties (who were not already mentioned above) for comment:

@trwnh@socialhub.activitypub.rocks @erincandescent@akko.erincandescent.net @mikedev@fediversity.site @jenniferplusplus@hachyderm.io

5 Likes

@julian @evan @jenniferplusplus @mikedev @erincandescent @evan @trwnh

>7888/171b use context whereas 76ea uses a new property thr:thread

I think context is good enough. Streams and NodeBB already provide this collection and Mitra will too.

>171b specifies a new object type Context

It is for easier identification of conversation-Add activities. My server may receive many different kinds of Add activities, and it would be nice to have some indication of what collection is being modified.

This is just an idea though. Streams uses Collection type

>Collection items:

My use case requires items to be activities, but I can support both variants of context collection. Conversation activities can be also put into a different collection.

@julian @evan @jenniferplusplus @mikedev @erincandescent @evan @trwnh

>7888/171b use context whereas 76ea uses a new property thr:thread

I think context is good enough. Streams and NodeBB already provide this collection and Mitra will too.

>171b specifies a new object type Context

It is for easier identification of conversation-Add activities. My server may receive many different kinds of Add activities, and it would be nice to have some indication of what collection is being modified.

This is just an idea though. Streams uses Collection type

>Collection items:

My use case requires items to be activities, but I can support both variants of context collection. Conversation activities can be also put into a different collection.

@silverpill@mitra.social said in FEP Convergence (400e, 7888, 171b/Conversation Containers, 76ea):

It is for easier identification of conversation-Add activities. My server may receive many different kinds of Add activities, and it would be nice to have some indication of what collection is being modified.

In that case, are you trying to sidestep a potential future conflict? I think I can see your rationale that duck typing "resolved context is a Collection" may not be specific enough, but I am not currently aware of anybody outside of 400e/7888 that has a context that even resolves to anything.

@silverpill @julian @evan @evan @mikedev @jenniferplusplus @trwnh

My plan is to bring Akkoma into conformance with FEP-7888. Contexts (as they implicitly exist) contain Objects in Akkoma today, and my plan is to make that collection dereferencable.

At the moment I have no plan to implement sending of Add activities though that could come in the future.

Regarding FEP-171B’s use of the Context object type, I am ambivalent. We will likely expose an (Ordered?) collection at first.

FEP-76EA’s definition of thr:thread doesn’t match how Akkoma maintains or interprets the Context today. My opinion is that I would only invest time in implementing it if implemetations actually coalesced around it; it doesn’t suit our needs. In particular the requirement “The tree structure of the thread should be maintained; every object in the thread collection, except the root, should have an inReplyTo property that matches the id of another object in the collection.” does not match how Akkoma handles quote posts (it places them in the same Context).

@erincandescent@akko.erincandescent.net Future discussions of the ForumWG may turn to more forum-like handling of context collections like forking, moving of posts, locking, pinning, etc.

In the former two cases, inReplyTo would no longer necessarily point to an object that is in the self-defined context collection. This is a very good point.

@trwnh@mastodon.social also made this point recently as well.

2 Likes

@julian

No, that's for target property. Here's an example of Add.target from Streams:

"target": {
  "id": "https://streams.lndo.site/conversation/ed4775f8-18ee-46a5-821e-b2ed2dc546e8",
  "type": "Collection",
  "attributedTo": "https://streams.lndo.site/channel/red"
},

In my code I have a handler for Add activity, which then sends activity to one of the other handlers:

- Add{target: featured}
- Add{target: subscribers}
- Add{target: context}

Currently I use heuristics to determine which one to use. But with Add.target.type == <meaningful type name> the code would be simpler and less fragile.

Do you have something like that in NodeBB? I wonder how others solve this "routing" problem

@julian

No, that's for target property. Here's an example of Add.target from Streams:

"target": {
  "id": "https://streams.lndo.site/conversation/ed4775f8-18ee-46a5-821e-b2ed2dc546e8",
  "type": "Collection",
  "attributedTo": "https://streams.lndo.site/channel/red"
},

In my code I have a handler for Add activity, which then sends activity to one of the other handlers:

- Add{target: featured}
- Add{target: subscribers}
- Add{target: context}

Currently I use heuristics to determine which one to use. But with Add.target.type == <meaningful type name> the code would be simpler and less fragile.

Do you have something like that in NodeBB? I wonder how others solve this "routing" problem

@silverpill@mitra.social said in FEP Convergence (400e, 7888, 171b/Conversation Containers, 76ea):

Do you have something like that in NodeBB? I wonder how others solve this "routing" problem

We do the same. We don't actually handle Adds right now, but our Update handler has a switch..case based on type.

Adding a separate type would be easier, yes. Otherwise you're looking at additional logic to tease apart different variants that share the same base object type. For example, the logic for Update(Note) has further logic paths depending on whether the note is publicly addressed or not.

So then yes, a Add{target: Collectionish} might be vague, but that's only the case if other implementations use the same.

1 Like

@julian This pattern can also be used in Accept and Undo activities:

{
  "type": "Undo",
  "id": "https://social.example/activities/undo/1"
  "object": {
    "type": "Like",    # or "Follow"
    "id": "https://social.example/activities/like/1"
  }
}

@julian This pattern can also be used in Accept and Undo activities:

{
  "type": "Undo",
  "id": "https://social.example/activities/undo/1"
  "object": {
    "type": "Like",    # or "Follow"
    "id": "https://social.example/activities/like/1"
  }
}

from my understanding, only 7888 and 171b do this. 76ea instead tries to establish a central view of a reply tree, which is not the same as a conversation. there are several cases where replies and context diverge:

  • replying to something in a different conversation (for example, when conversations get forked or posts get moved to a new conversation)
  • participating in a conversation without replying
  • replying without participating in a conversation

also, there is the consideration that context is used for grouping, even if it’s not resolvable. so it gracefully falls back to basic grouping behavior in the simplest case. thr:thread doesn’t do this.

you can send a Remove in all three FEPs, it might just not be called out explicitly. the use of Add/Remove is a courtesy to anyone else following along, so they don’t have to fetch the collection manually every single time. (although fetching the collection every single time is inefficient, it is the only way to have a guaranteed consistent state, so there are reasons why you may want to browse the collection “at the authoritative origin”, so to speak.)

i am not strictly opposed to this, but neither do i support it. it might end up being useful to define a type that means “this specifically represents a collection whose items share the same context property” (as i think Context is trying to do), but this should not be required.

similarly, we could define a type that means “this specifically represents a collection whose items all have content” (we could call it Conversation or CollectionOfPosts or CollectionOfContentfulObjects or whatever) but this is similarly something that shouldn’t be required.

the reason that i think such types shouldn’t be required is that not only are they not necessary for the basic mechanisms to work, they also might be misleading or incorrect, because ultimately the contents of any collection are solely decided by whoever owns the collection. i could declare that a collection is a Context and then immediately after this i go and Add a bunch of objects that don’t have that context, or any context at all for that matter. this is something that is going to be very relevant in the interim where NodeBB and similar implementations continue to have behavior for traversing reply trees and attaching posts to topics that aren’t explicitly declared as context. (not that i think this behavior is necessarily always correct, either – it’s just something that could be done, and is probably useful to do, insofar as other implementations continue to remain unaware of context and its grouping properties. you could just as equally convert posts with inReplyTo but no context into NodeBB Chat Messages instead of NodeBB Topic Posts… but this is an implementation decision.)

7888 is agnostic as to what the exact contents are, aside from them ideally all sharing the same context – you could have a 7888 collection contain any type in any order. however, with that said: i favor post objects (anything that has content) in forward chronological order, because this is what is most useful to the casual browser. i don’t know of any forum software that chooses to present threads in reverse order with the newest posts at the top. they usually do this for topics, but not for posts.

also: these are “defaults”, and ultimately we should probably move toward explicitly signaling how collections might be ordered or sorted, as well as providing a mechanism for requesting non-default presentations like “show me this thread in reverse chronological order” (?reversed=true or ?sort=newest or whatever) or “show me posts starting at index 69 and containing 7 items” (?startIndex=69&window=7). to that end, i recently submitted fep/fep/1985/fep-1985.md at main - fediverse/fep - Codeberg.org for declaring an OrderedCollection to have an explicit orderType of ForwardChronological or ReverseChronological. i also have a pre-draft of a FEP dealing with collections that are not just ordered sets, but specifically sorted sets. this would define SortedCollection as an extension of OrderedCollection, as well as defining a sortedBy property pointing to a vocab term, plus a sortType of either Ascending or Descending. there’s Pre-FEP: Evolving OrderedCollection to be more useful as the thread exploring this.

regarding the signaling of any given collection or actor following a specific protocol, i think we should define that explicit protocol before defining types. my old draft of FEP-9988 for “Federated Forums” was put on hold for exactly this reason – there are simply too many protocol considerations that need to happen first. Desired UX for forums, and accompanying user stories or Desired UX for forums, and accompanying user stories | NodeBB Community exists as a thread to collect user stories for forum UX that should directly inform the development of such a protocol.

1 Like

@julian i replied from socialhub but it seems to not have made it across yet... again :x https://socialhub.activitypub.rocks/t/fep-convergence-400e-7888-171b-conversation-containers-76ea/4669/12

@trwnh@socialhub.activitypub.rocks said in FEP Convergence (400e, 7888, 171b/Conversation Containers, 76ea):

i don't know of any forum software that chooses to present threads in reverse order with the newest posts at the top.

I'll bite. NodeBB lets you choose how to sort the posts. Chrono, reverse, or by vote count. Q&A forums might elect to use the latter two. But that's neither here nor there, it's a frontend UX thing and shouldn't really have any bearing on an AP S2S implementation detail.

1 Like

It has bearing on anyone browsing the linked data, as brought up immediately after:

Basically, imagine using https://browser.pub (or any other Web browser, really). The representation you serve in response to any GET request should be usable without requiring additional processing. You should be able to follow links normally like any other browser. This is the foundation of linked data.

2 Likes

@julian @silverpill @trwnh @erincandescent @mikedev @jenniferplusplus@hachyderm.io obviously `context` isn't good enough to identify the thread relationship. Trying to hijack it is contrary to the AS2 spec and common interoperability. One proposal tries to specify it by duck-typing every object; the other by defining a new Collection type. The clearest way to define the relationship is with a property, `thread`, which is specific, clear, and requires no other changes.

@julian @silverpill @trwnh @erincandescent @mikedev I think most developers understand that the reply tree and the conversation are identical. The use cases a describes -- forking, etc. -- can be implemented with `Announce`, perhaps with `content` in the `Announce` activity. I'll add these next week and push a new draft.

@julian @silverpill @trwnh @erincandescent @mikedev I think most developers understand that the reply tree and the conversation are identical. The use cases a describes -- forking, etc. -- can be implemented with `Announce`, perhaps with `content` in the `Announce` activity. I'll add these next week and push a new draft.

@evan @julian @silverpill @trwnh @mikedev "context" isn't good enough to identify any relationship; this is the fundamental problem. It is a property that should never have existed. Today it identifies one relationship: the (loosely defined) thread. I would argue that this is in fact "common interoperability". I would also argue that this fully meets the incredibly vague letter of the ActivityStreams specification.

I have yet to see an alternative use of context that would not be better served by inventing a more specific term. Yes, this applies to use of context for thread too, but we have 7 years of its user to identify the thread as a defacto standard.

1 Like

@evan @julian @silverpill @trwnh @mikedev "context" isn't good enough to identify any relationship; this is the fundamental problem. It is a property that should never have existed. Today it identifies one relationship: the (loosely defined) thread. I would argue that this is in fact "common interoperability". I would also argue that this fully meets the incredibly vague letter of the ActivityStreams specification.

I have yet to see an alternative use of context that would not be better served by inventing a more specific term. Yes, this applies to use of context for thread too, but we have 7 years of its user to identify the thread as a defacto standard.