FEP-7888: Demystifying the context property

Hello!

Please use this thread to discuss FEP-7888 and any potential problems or improvements that can be addressed.

Summary
ActivityStreams Vocabulary defines the context property, but it is “intentionally vague”. Unfortunately, this makes the definition so vague as to be practically useless. This FEP aims to provide more guidance on possible uses of the context property, as well as formalizing some best practices.

Full text: FEP-7888: Demystifying the context property

2 Likes

i’d like feedback from @Claire @macgirvin @nutomic @grishka in particular, as we’ve had prior discussions that intersected with this FEP:

  • @Claire @macgirvin there is the use of context to represent a “conversation”, which iirc is largely compatible with what Streams does and would be a reasonable extension to how Mastodon processes threads. strategically, i think it also makes sense to apply the “approval” workflow of FEP-5624 to contexts instead of direct replies; however, there is room for both “reply approval” and “context approval”, although there is still the issue that any approved reply can be a trojan horse for further replies you may wish to avoid but cannot, due to having no authority.
id: example.com/conversations/1
attributedTo: example.com/some-authority
type: Collection
orderedItems:
  - example.com/posts/1
  - example.com/posts/2
  - example.com/posts/3

id: example.com/posts/1
type: Note
context: example.com/conversations/1
content: "hello world"

id: example.com/posts/2
type: Note
context: example.com/conversations/1
content: "hi"
inReplyTo: example.com/posts/1

id: example.com/posts/3
type: Note
context: example.com/conversations/1
content: "hello to you too!"
inReplyTo: example.com/posts/1
  • @Claire @grishka there is the use of context to represent a “wall” as well, which i think is compatible with the intention behind FEP-400e, just that it doesn’t use target which is invalid on Object and only defined for Activity. this usage is relevant to “groups” as implemented by Smithereen and by the Mastodon PR.
id: example.com/groups/1
inbox: ...
followers: ...
audience: Public

id: example.com/groups/1/wall
attributedTo: example.com/groups/1
audience: Public
type: OrderedCollection # signals reverse-chronological
orderedItems:
  - example.com/posts/140
  - example.com/posts/139
  - # can either contain more contexts representing conversations,
  - # or can contain the objects directly if a flat structure is desired

id: example.com/posts/139
type: Note
context: example.com/groups/1/wall
content: "Hello world"

id: example.com/posts/140
type: Note
context: example.com/groups/1/wall
content: "Greetings, everyone"
  • @nutomic there is the use of context to represent a “forum”. i’m not sure how compatible or disruptive this would be for Lemmy, but with regards to FEP-1b12 it does recommend a different distribution mechanism in Add instead of Announce. as far as context might be applied to Lemmy, you could use it for Lemmy’s equivalent of a subreddit. if i’ve read the fep right, then this might be what you currently use audience for? whereas audience would be best used to indicate who can see the object rather than which lemmy community it’s in. a lemmy community would be best thought of as a Collection that is also an actor that can be followed. so maybe like so:
id: lemmy.ml/c/policypeanuts
preferredUsername: policypeanuts
audience: Public
attributedTo: # can update and delete the community
  - lemmy.ml  # the instance actor 
  - example.com/some-external-mod # optional
inbox: ...
followers: ...
type:
  - # some primary type, like Application or Group (or both?)
  - OrderedCollection
orderedItems:
  - lemmy.ml/post/840974
  - lemmy.ml/post/838721
  - # more posts...

id: https://lemmy.ml/post/840974
name: "RIC is not enough"
attributedTo: lemmy.ml/u/roastpotatothief
context: lemmy.ml/c/policypeanuts
audience:
  - Public
  - # the community
  - # the community's followers
replies: ...
3 Likes

As you say, Lemmy uses audience to specify the Group that an object or activity belongs to. audience and context are both defined rather vaguely in the activitystreams-vocabulary, so I agree that they could be used interchangeably. However FEP-1b12 is already finalized so its not possible to change at this time.

Im not sure why you want to think of a Lemmy community as “an actor that can be followed”. It is precisely a Group which is one of the standard actor types. The collection you are thinking of is the group’s outbox. Including the instance actor in attributedTo is a interesting idea though, that might be useful to add in the future.

the suggestion was to multi-type as both Group/Application/whatever and also as OrderedCollection, so that you could make use of orderedItems following the general recommendations to treat context as a collection. but this is not necessary; you could disregard that part and still follow the part about delivering only to context.attributedTo.

i suppose we could consider language saying that if the context is not a Collection (i.e. doesn’t have orderedItems or items), then you should check outbox if present (i.e. if the context is an actor)? this is a bit weird though, so i’m inclined not to do that.

the reason i didn’t suggest context = outbox is because you aren’t really creating the object in context of the outbox; the outbox instead contains the actor’s Add/etc activities. also in many cases where the user desires privacy, the outbox should not be public. it might make sense to (re)use smithereen’s wall property to signal this as a special collection on the actor, but i don’t think this should be necessary. you could just have the collection be the actor. activitypub is very clear about this:

ActivityPub actors are generally one of the ActivityStreams Actor Types, but they don’t have to be. For example, a Profile object might be used as an actor, or a type from an ActivityStreams extension.

tangentially, i think it is a big mistake to treat actor types as having additional meaning and expectation that isn’t defined by anything. the standard as2 actor types are more like vcard kinds than they are separate classes. declaring your actor is a Group doesn’t actually imply anything technically different than declaring yourself a Person or Organization or Application. you still receive activities in your inbox and send out activities to your followers. these types are basically only useful for display differentiation, along the lines of saying “this is a personal account” or “this is a brand account” or “this is an automated account” or “this is a collective account”. we might reasonably declare an actor to be a [Group, Application, OrderedCollection] which semantically means “this actor represents a collective and is automated. it also contains items that are sorted reverse-chronologically.”

the ability to Follow threads and conversations is discussed further in Unresolved issues surrounding Follow activities

yeah, i brought up FEP-1b12 as something related to this, not as a recommended change, as it prescribes different behavior. i think it is roughly incompatible with some of what FEP-1b12 defines. things like the Follow flow are standard to activitypub, things like saying that a Group is automated are less so. things like specifying that audience must be a singular value or that Announce MUST be used are especially unfortunate, as audience is an array of who can see an object, and Announce is specifically a reshare or crosspost that gets added to the shares collection. i think this also precludes private sharing in the future? not entirely sure, but it seems that way.

FEP-1b12 might be finalized but that doesn’t mean we have to use it forever. the aim of this FEP-7888 is to provide a framework that isn’t specific to any one interpretation of “what is a group” vs “what is a chat” vs “what is a conversation” vs “what is a topic” vs “what is a forum” vs “what is a thread”. the presentation is irrelevant to the underlying data structure: objects in collections. they all operate the same way. that’s what “context” is: a logical grouping of these related objects. it would be great if fediverse implementations end up converging on this structure that can be presented in multiple different ways. it’s probably going to take some time, though…

1 Like

I read the FEP text now. For me the biggest question is if the context field is currently in use anywhere, or if you are planning to use it in a particular way. That information would be good to include in an “implementations” section to have something more concrete than the sample workflow. I would also include some sample JSON to see how the data related to context looks concretely.

You are mentioning to use context to represent forums. In this case you should include a reference to the FEP-1b12 as thats how forums are currently implemented in Activitypub in the real world. Your FEP could be complementary to that for representing things like conversations, but it needs more clarification for that.

This may be done with inbox forwarding or by delivering an Add activity. An Announce activity SHOULD NOT be used, as this would be interpreted as a reshare. (Verification mechanisms for inbox forwarding or Adding private objects is out-of-scope for this FEP.)

I think this needs to be specified more concretely if you want projects implementing this to be compatible. Regarding inbox forwarding do you have any links explaining how it works?

Back to your last post, Im still not entirely sure where you are going with this. Are you proposing to make Lemmy compatible with your proposed usage of context? For that I would need to see a concrete implementation first.

Its true that there is no fundamental difference between actor types, but its obvious to me that the different types should indicate different behaviour. For example bot accounts have the type Service. I am strictly against objects with more than a single type value because it is very difficult to parse, and I honestly dont see any advantage to it.

Regarding FEP-1b12 you seem to be under the impression that it is proposing new behaviour, or something that is only used by Lemmy. That is not true, the exact same behaviour using Announce is also used by Peertube, Hubzilla, Friendica and Lotide. The only addition is the audience field which is defined as “object” by activitystreams-vocabulary, so using it to specify the group actor seems fully compliant.

I suppose you are proposing this new FEP because you plan to implement a simpler version of groups which doesnt need the functionality required by projects mentioned above. I dont think thats a good tradeoff. One major limitation I can see is that each FEP-7888 forum would be bound to a specific Person for sharing its activities. This makes it impossible to transfer ownership of the forum to another user. With a Group actor its enough to change attributedTo to add or remove owners (moderators), or to transfer ownership. It is also not clear where things like forum title, description, icon etc would be stored on such a collection. There are probably more limitations that Im missing now. For these reasons I dont think that any of Peertube, Lemmy, Friendica etc would be technically able to switch to this federation model, because its too limited. Not to mention that all of them already federate successfully with the model described in FEP-1b12, so there is no reason to rewrite everything.

If you want to implement group federation, the better decision is to go with the existing model. True it is more complex and supports things which you dont need, but other platforms do require it and its worth the effort to federate with them.

current use of context

I guess I can add something like that, yeah. As far as I know, the context currently goes largely unused:

  • Pleroma attaches it as a tag that is not meant to resolve, similar to ostatus:conversation, and then it gets ignored because constructing threads is largely based solely off of inReplyTo in Mastodon et al.

From Mastodon:

  "conversation": "tag:mastodon.social,2023-03-17:objectId=416298421:objectType=Conversation",

From Pleroma/Akkoma:

  "context": "https://skinnyver.se/contexts/e085588b-cc4e-4a98-8a6d-7dc015c33135",
  "conversation": "https://skinnyver.se/contexts/e085588b-cc4e-4a98-8a6d-7dc015c33135",

Failing to resolve that context:

$ curl -H 'Accept: application/activity+json' https://skinnyver.se/contexts/e085588b-cc4e-4a98-8a6d-7dc015c33135

<!DOCTYPE html><html lang=en>...<noscript>To use Akkoma, please enable JavaScript.</noscript>...</html>
  • Streams attaches it on posts and activities
"context": "https://macgirvin.com/conversation/399fba05-68ad-40c7-902b-57c0518547b1",

this actually resolves. it is an OrderedCollection with all activities as seen by the origin. abbreviated response:

  "id": "https://macgirvin.com/conversation/399fba05-68ad-40c7-902b-57c0518547b1",
  "type": "OrderedCollection",
  "totalItems": 13,
  "orderedItems": [
    {
      "type": "Update",
      "id": "https://macgirvin.com/activity/399fba05-68ad-40c7-902b-57c0518547b1",
      "context": "https://macgirvin.com/conversation/399fba05-68ad-40c7-902b-57c0518547b1"
      "object": {
        "type": "Note",
        "id": "https://macgirvin.com/item/399fba05-68ad-40c7-902b-57c0518547b1",
        "context": "https://macgirvin.com/conversation/399fba05-68ad-40c7-902b-57c0518547b1",
    },
    {
      "type": "Create",
      "id": "https://rumbly.net/activity/4f392617-57a6-4a51-90f8-9c4440640aea",
      "context": "https://macgirvin.com/item/399fba05-68ad-40c7-902b-57c0518547b1",
      "object": {
        "type": "Note",
        "id": "https://rumbly.net/item/4f392617-57a6-4a51-90f8-9c4440640aea",
        "published": "2023-03-17T21:26:33Z",
        "attributedTo": "https://rumbly.net/channel/giacelvecio",
        "inReplyTo": "https://macgirvin.com/item/399fba05-68ad-40c7-902b-57c0518547b1",
        "context": "https://macgirvin.com/item/399fba05-68ad-40c7-902b-57c0518547b1",
    },
// ...

representing “forums” with FEP-1b12

i could add a reference to other tangential FEPs within 7888, but the point of context is not just to represent “forums”. it is a general definition for representing any logical grouping. “this object is part of this collection”, if that context is a collection. or, inversely, “a collection may be created containing all objects referencing this context” would be the weaker definition.

incidentally, i consider “forums” to be currently unimplemented in activitypub, because 1b12 only loosely represents announce-bots that boost anything sent to them. it’s a model that has better compatibility with what currently exists, but it has many shortcomings that make it unsuitable for organizing and grouping information.

it also fails to account for generic activitypub servers, which might interpret audience as meaning “only the group actor can view this” and refuse to serve the objects to anyone else.


specifying Add to Collection, or inbox forwarding, as an alternative to Announce

add to collection

Add is exactly what it sounds like, and it is already defined in ActivityPub. it would look something like this:

id: ...
actor: alice
type: Add
object: <some-object>
target: <some-collection>

per ActivityPub

7.8 Add Activity

Upon receipt of an Add activity into the inbox, the server SHOULD add the object to the collection specified in the target property, unless:

  • the target is not owned by the receiving server, and thus they can’t update it.
  • the object is not allowed to be added to the target collection for some other reason, at the receiver’s discretion.

so basically the target collection should be owned by the recipient and the recipient also has the option to verify this.

basically we don’t have to be passing around exclusively Create activities. in some ways, a Create activity is actually worse, because it doesn’t represent what is really going on semantically. FEP-400e shows this by trying to use target on objects where they are only defined for activities; it does this because the primary activity is a Create, and target doesn’t really make sense on a Create either. it makes sense on Add and Remove, though, so why not actually use Add and Remove?

inbox forwarding

it’s not spelled out explicitly in the activitypub spec, but i think inbox forwarding is basically just POSTing to some other inbox exactly what you received. say you receive a Create Note and it addresses your followers. you can choose to forward that Create Note exactly as you received it, by sending it to your followers as-is.

typically, this requires some signature mechanism to prove the activity came from the original actor. but this is only really needed for private activities. public activities might reasonably be fetched from the origin if they are fetchable. say you want to forward a Like, and the Like isn’t public. you would need a signature on it (and for all participants to agree on a common signature mechanism)


where i’m going with this

i am approaching this problem from purely theoretical terms, as a shortcoming of the ActivityStreams specification, where they left the definition “intentionally vague” to the point of being useless. as a consequence, the FEP is not an implementation guide but rather a spec definition. it is of course up to Lemmy to choose whether a spec should or should not be followed, or if “real-word” compatibility is more important. my aim is to provide spec language that can be followed, and if followed, it would improve compatibility by eliminating the implementation-specific hacks that arise purely from implementation-specific abstractions.

i “plan” (hopefully!) to pave the way for generic activitypub servers that do not know and do not need to know what a “group” is. what is needed is standardized behavior around adding things to collections or logical groupings, which is what a “context” is. the “further FEP” mentioned will be to do the following:

  • prove that an object is part of a context it claims to be part of (alternative to FEP-5624’s approval or replyApproval)
  • signal who can participate in a context (similar to 5624’s canReply; i’m not yet sure if audience can do this, as there still needs to be a way to control who can see the context at all)

audience as the group actor vs audience as scoping

it is compliant, but it does not mean what you think it means. the use of audience is to scope objects to a particular audience, i.e. who is intended to see it. Activity Vocabulary

if you were to actually implement such scoping, this would mean that only the Group actor should see the activity. the Group’s followers should not be able to see it.

multiple types

type is not functional, and you should be checking for inclusion in that set, not an exact match. anything not marked “functional” in AS2-vocab can have multiple values. other examples of this include multiple actor, multiple object, multiple attributedTo, multiple inReplyTo, even multiple context. doubtless any or all of these might break existing implementations due to their (terribly incorrect) assumptions.

the advantage to having multiple types is apparent once you consider extensions. if you say type is a single value, and you actually check for type, then you are now responsible for understanding every single extension type that may ever exist, as well as all of its implications.

an example of this is OrderedCollection, which specifically guarantees that the “order” of the collection is “reverse chronological”. if you have this guarantee, you can do things like fetch only the newest pages from the start until you encounter something you’ve already seen. (there might still be gaps, but if you don’t care about gaps, you can stop there.) if you have an extension type that satisfies this requirement, you have no way of signaling this to unaware consumers. say we defined a ForumTopic/ChatRoom/SocialMediaThread type or something similar. what would this mean to us, and what would this mean to a consumer? to us, we would define the type as a Collection that contains objects and activities, and not other Collections. the ordering may or may not be reverse-chronological; it may in fact be forward-chronological. if we wanted to signal both “this collection is terminal and does not contain any other collections” as well as “this collection is ordered reverse-chronologically”, we would need to declare both types.

another example: what if an account represents both an organization and an automated application? do you declare it to be an Organization, or an Application? the former means it won’t have a “bot” indicator and the latter means it won’t have an “org”/“brand” indicator. you might reasonably want both signals. your only other option is to define an extension type like UnmonitoredBrandAccount, and good luck getting that recognized.

more generally, a “type” should be thought of as an interface that can be satisfied. in computer science terms, a type is a set containing all possible values, and satisfying the type interface means being a member of that set. the activitystreams actor types are not really “types” in this sense, but more like vcard “kinds”. you have the following “type” interfaces in activitystreams/pub:

  • Link = has href
  • Object = doesn’t have href
  • Activity = has actor and object
  • IntransitiveActivity = has actor but no object
  • “actor” = has inbox + outbox
  • Collection = has items or orderedItems
  • OrderedCollection = the orderedItems are ordered reverse-chronologically
  • CollectionPage = has partOf + has items or orderedItems
  • OrderedCollectionPage = has partOf + the orderedItems are ordered reverse-chronologically

any assumptions beyond these are incorrect and have no justification. famous examples of wrong assumptions include “an actor must be one of the five extended actor types” or “tag must contain only Mention or Hashtag or Emoji”. this kind of fragility arises mainly when an implementation thinks about its business logic more than it thinks about the spec, and so it compromises the latter in order to contort it to fit the former.


misconceptions

yes, i am aware. this behaviour is also used by Guppe, and could be used by bots implementing the mastodon api to talk to mastodon/pleroma, or could be used by bots implementing the misskey api, and so on. in all of these cases, they are reshares. reshares are not the aim of this FEP; this FEP operates on objects and collections (or objects and logical groupings, if there is no resolvable collection).

FEP-7888 does not define “forum” so much as it defines “context” which can be used to represent a forum as a collection of threads/topics. the keyword here is “collection”.

for ownership, you still use attributedTo. you can update the attributedTo on the collection just like you can on the Group actor. whoever owns the collection is in charge of distributing the Add/Remove activities to maintain that collection.

these are all implementation details – the title would be name, the description would be summary, the icon would be icon, none of these things are different than the general pattern for any other object. i’m not sure of any other limitations, but if you find any more please let me know so that i can address them or clarify the FEP language.

“switching to this federation model” doesn’t actually represent a major change, as it’s something that should be supported by plain activitypub. think of it like this: after you create an object, what do you do? you might add it to a collection, right? the only real “switch” in this case would be to maintain this collection instead of expecting everyone else to maintain it ad-hoc for themselves anyway, as we currently do. this can be done by sending out Add activities either instead of or in addition to the existing Announce flow.

hopefully i’ve shown by now that i do not wish to implement “group federation”. you might think of it as “collection federation”, where the collection is possibly being managed by some authority who gets to decide what’s in the collection. this collection might be any number of things, not limited to groups or forums but also representing chat rooms or comment threads or social media walls. it does not matter what type the owning actor is – they may be a Group actor, they may not be! it’s irrelevant – what matters is the general behavior of maintaining some authoritative collection (and signaling its moderators). it’s worth the effort to not limit ourselves to Create Note or in some cases Create Page. you should be able to browse the actual objects just like anything else on the World Wide Web.

2 Likes

Can you give example of how this would be used/implemented in #OMN and #indymediaback this is worthwhile because we need better use of examples.

"#OMN the feeds are the pipes to join the data cauldrons. Site/apps are ladles that scoop out data, we are the hands that hold the ladle. The coding basic iron work framing of these tools.

Cauldron - syncing database
Pipe - #4opens standard flows of data
Ladle - website/app that displays data"

i’m not sure what OMN and indymediaback look like conceptually – i guess the “data cauldron” could be the activitypub server, the “site/apps” and “ladles” are activitypub clients or activitystreams/jsonld user-agents, and “we” are the user who uses the user-agent. you could just as easily browse the linked data web in the same way you browse the html web.

what a “context” would allow you to do is to maintain a collection of other objects – say, a bunch of Pages that make up one of the streams on your Profile. an activitypub Client could take those and render some HTML, and now you have a traditional website. so you could represent a folder or directory using context. it’s all in the semantics.

1 Like

Okay I understand it much better now. For me this FEP doesnt seem relevant currently, but hopefully it will be useful for other projects.

incidentally, i consider “forums” to be currently unimplemented in activitypub, because 1b12 only loosely represents announce-bots that boost anything sent to them. it’s a model that has better compatibility with what currently exists, but it has many shortcomings that make it unsuitable for organizing and grouping information.

Which are those shortcomings? Because Im not really aware of any.

it’s not spelled out explicitly in the activitypub spec, but i think inbox forwarding is basically just POSTing to some other inbox exactly what you received. say you receive a Create Note and it addresses your followers. you can choose to forward that Create Note exactly as you received it, by sending it to your followers as-is.

This would fail the HTTP signature check because the target domain is part of it. And if the forwarding instance creates a new signature, how would you retrieve the public key for verification if not from activity.actor?

wait, shouldn’t you be getting the keyId from the HTTP Signature: header?

in any case, yes, there are challenges in verifying anything you receive, but this is no different than a regular activity.

  • HTTP Signatures let you verify who sent it
  • LD Signatures let you verify who wrote it

in the case of inbox forwarding, http-sigs would still require you to trust that the forwarder is not making anything up. just like in email, any “forwarded email” you get is not verifiable without something like a PGP signature and a chain-of-trust on who claims to own the PGP key.

but also, sometimes you want to be able to deny sending a message. there is a choice you have to make between provenance and repudiation.

of course, if the object or activity is fetchable, then you can just fetch it from the origin and there is nothing to verify. imagine posting a bare id to an inbox. you could even require authorization via a bearer token, if you wanted to be secure (although you’d need a way to assign and manage such tokens to your intended audience). the idea is that the initial POST to inbox is just a notification or signal to go fetch the document from the origin, which you implicitly trust because it’s the source of the data. (you might still want to do an additional check that the actor is on the same domain as the activity, though.)

1 Like

the main shortcoming of using Announce is that you’re using Announce. semantically, this represents a share/reshare/boost/retweet/repost/etc. when received in the inbox, it gets added to the shares collection if one exists. it is a post type/kind on its own. implementations render it as such. it’s like a robot repeatedly saying “hey, look at this!” – following such an actor in effect means you get spammed with such activities.

another notable shortcoming is that you can’t moderate effectively or naturally. what do you do, Undo Announce Create Note? or do you expect Announce Delete Note from the moderators to be honored on someone else’s object? what if that object is public and fetched from the origin, causing the offending submission or comment to reappear?

this is fine, it doesn’t have to be relevant to everyone, but i still think it could be relevant to Lemmy for grouping comments on a submission. generally speaking, the concept of a “context” is broadly useful to anyone who wants to group things and then process them together in some way.

1 Like

That is only true for Mastodon and similar projects, not the ones mentioned in FEP 1b12. And activitystreams-vocabulary describes Announce as “Indicates that the actor is calling the target’s attention the object”, so I think that fits. Anyway if thats a problem, the solution can’t be to have multiple projects rewrite major parts of their federation code. It would be much simpler if Mastodon etc treated Announce activities differently, depending if they were sent by a Person or a Group.

Lemmy uses Announce/Delete/Note in that case. There are no reappearing comments because restoring a comment takes Announce/Undo/Delete/Note. So its just wrapping normal activities in Announce, pretty simple and works well.

no such distinction exists at the protocol level… an actor is an actor. the server should process side effects the same regardless.

ok, so putting aside that you allow someone to “delete” an object they do not own… do you then not resolve any objects from origin ever? or do you keep track of the id of every single moderated object in order to prevent resolving “deleted” objects that still exist?

this seems very messy when you could instead treat the community or comments section as a context from which things can be added and removed by the owner.

The thing with context is that it’s already used by some software to keep track of which conversation a reply belongs to. I specifically chose target because it’s unambiguous and it also carries different semantics than context (i.e. gives the collection owner authority over the object).

My FEP makes it valid.

i don’t think the semantics are actually different. or rather, the semantics of target is incorrect. if you were to translate target to plain english, it would be something like “Sally Created a Note to target” , which doesn’t really make sense. what you should be saying is something like “Sally Created a Note in this context”. a “context” is precisely what you ascribe to target – you are describing an authorized context, which is basically a logical grouping managed by some authority, where the owner has authority over objects in the context and can Add/Remove them. this is not actually any different than a “conversation”. the only practical difference is in whether this conversation/context is set (and “owned by” or attributedTo someone), or if it is not set (and therefore essentially in the global context).

another way to think of it is, if you encounter just the object, the context is basically the “see also” link. “you may want to view this other object first/instead/additionally, as this object alone might not make sense without that context.” in much the same way that taking a single post out of the “thread” or “conversation” or “comments section” might lead to confusion without being able to see the rest of the context.

If context will be a collection, what other property implementers can use to indicate relationship between objects? Example from Activity Vocabulary:

An example could be all activities relating to a common project or event.

“Intentionally vague” context property was useful when relationship you want to describe can’t be described by other more specific properties like inReplyTo, attributedTo or origin.

I think you can still use context for that, it just doesn’t have to be a Collection. The additional behavior described in the FEP only applies iff the context is both resolvable and also resolves to a Collection. It’s fine to have context be something else. Basically you have two aspects to it:

  • Grouping. Two objects sharing the same context declaration are logically grouped together in some way. (This naturally lends itself to having the grouping expressed by a Collection, but it doesn’t have to be.)
  • “See also”. An object with a context declaration is signaling some origin or purpose beyond the current object; I like to think of this as saying that the object doesn’t really make full sense without the context. (Again, if it’s a Collection, this is expressed naturally.)

The AS2 consumer needs to be able to handle any of the following cases:

  • It’s missing (do nothing)
  • It’s unresolvable (group by opaque string comparison)
  • It’s resolvable to something that isn’t a Collection (group by id of that object)
  • It’s resolvable to a Collection (group by id of that object, and also you can process its items or orderedItems)

Basically it’s a series of breakpoints. “And if you do… then also…”

1 Like

In general, it’s a lot better to use a more specific, defined extension term rather than laying claim to an intentionally vague property from the Activity Vocabulary.

If there’s an intention to include a link to a collection that contains the full replies tree from an original (no inReplyTo) post, using a very specific term in an extension namespace is a better practice.

It’s perfectly OK to use context for this or any other use – that’s what it’s there for – but if you’re trying to define a new specification with clear semantics and functional interoperability, it’s better to define a new, specific term.

The intent is that this is completely parallel and unrelated to replies.

In “The existing definition” and its subheadings, I talk more about why context is used and what “context” means in various linguistic senses:

context exists to form a purposeful grouping, regardless of the specific purpose

I derive this from the definition of the AS2-Vocab term (emphasis mine):

The intended function is to serve as a means of grouping objects and activities that share a common originating context or purpose

Looking further into the intent, there is this Github issue in which James Snell describes context and audience (previously called scope) as similar properties (emphasis again mine): scope v context · Issue #300 · w3c/activitystreams · GitHub

The scope indicates that the audience for the note is only members of the Organization.
The to indicates specific people who should be actively notified.
The context indicates a larger context within which the note exists.

To be clear: scope is not access control… it is closely related to to/bto/cc/bcc in that a consuming implementation can use it to determine who it ought to display the content to. So, for instance, given the note example above, a consuming implementation may include the note on the activity timeline of anyone associated with the ‘My Employer’ organization, but it would only activity notify two individuals listed by the to property. The context property, on the other hand, has absolutely nothing to do with audience targeting. The above note is essentially saying, “This is a note that was created in relation to A Project. Make the note available to anyone in the My Employer organization but specifically notify John and Sally”

From another issue (emphasis mine): [Proposal] Drop `context` from AS Vocabulary to avoid confusion with `@context` · Issue #238 · w3c/activitystreams · GitHub

The context is really intended to allow objects and activities to be
logically grouped. For instance, in an enterprise setting, the context may
group activities by project while the scope would identify one or more
teams for which the activity is considered relevant, while the to/cc fields
are used to indicate specific individuals to notify.

So there’s plenty of precedent and design intent to use context for “purposeful grouping”. In the FEP, I contrast this with tags, which are a much looser relation:

The key property of such a tag is to signal a general, implicit association by reference. We might then consider a context to be an explicit association

context should be something that helps you process the activity or object. Ignoring the context may lead to misunderstanding the activity or object; the object or activity exists within that context.

Everything that follows from this point is a series of logical conclusions and progressive enhancements layered on top of each other:

  • If there is no context, then there is nothing to do
  • If there is a context, then use it for grouping
  • If the context resolves, then use its id for grouping, and also you may want to look at that object and do something with it.
  • If the context resolves to specifically a Collection, then use its id for grouping, and also you might want to look at that collection and do something with it.

Put another way, it’s a series of SHOULDs and MAYs intended to provide guidance on what to do with a context if you encounter one. Any functionality is in keeping with the intent of the term, the semantics of its definition, and its existing usage in fediverse implementations like Pleroma and (streams) – and since then, Discourse and NodeBB have adopted its usage along these lines. I could list these implementations within the FEP, but I don’t do this because there aren’t any hard requirements to comply with… just some guidance on how it could be used. I don’t really see a reason to define some specific term that doesn’t meaningfully differ from the existing term we already have. My hope with writing this FEP was merely to clarify the “intended usage” while clearing the air on the “intentionally vague” bit, which I believe was meant to caution against locking into any specific interpretation of what the value of context ought to be.

2 Likes

FEP updated via #438 - 7888: Clarify normative text, add more examples, fix references - fediverse/fep - Codeberg.org to add more clarifying text and examples.

There might be a follow-up FEP if I can find any other points of confusion to clear up. I’m still looking through prior conversations, but I think one additional thing I can add more description of is “what to do when context isn’t a collection”. It’s currently mentioned in passing that you would use the id to group objects you’re aware of, but I could expound further.

1 Like