From cbe48ff7da5648abd480a3b8dd08192fc55f597d Mon Sep 17 00:00:00 2001 From: a Date: Mon, 1 Jan 2024 19:44:11 +0000 Subject: [PATCH] Update FEP-7888 (#222) clarify some language and add an example flow Reviewed-on: https://codeberg.org/fediverse/fep/pulls/222 Co-authored-by: a Co-committed-by: a --- fep/7888/fep-7888.md | 103 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 9 deletions(-) diff --git a/fep/7888/fep-7888.md b/fep/7888/fep-7888.md index 1124de3..d0bebc1 100644 --- a/fep/7888/fep-7888.md +++ b/fep/7888/fep-7888.md @@ -25,7 +25,7 @@ Aside from being "intentionally vague", the definition is also somewhat circular ### Purpose and intent; or, why not use a tag? -We might similarly use a `tag` for grouping objects and activities. Current fediverse projects often include a `Hashtag` (defined as an extension within the ActivityStreams namespace, but not actually adopted or defined formally). This `Hashtag` signals an intent to be included or discovered through a collection of objects bearing the same `Hashtag`, uniquely identified by its `name`. The maintenance of such collections is assumed to be the responsibility of the receiving server, although an `href` is provided for convenience, in order to browse the collection of tagged objects at the source. (This also makes the `Hashtag` a sub-type of `Link`.) +We might similarly use a `tag` for grouping objects and activities. Several fediverse projects often include a `Hashtag` (defined as an extension within the ActivityStreams namespace, but not actually adopted or defined formally). This `Hashtag` signals an intent to be included or discovered through a collection of objects bearing the same `Hashtag`, uniquely identified by its `name`. The maintenance of such implicit collections is assumed to be the responsibility of the receiving server, although an `href` might be provided for convenience, in order to browse the implicit collection of tagged objects as seen from that origin server. (This also makes the `Hashtag` a sub-type of `Link`.) 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, but such an explicit association requires an explicit definition. @@ -39,7 +39,7 @@ Specific contexts can be thought of in several applications: - the "conversational context" is a context which represents some conversation and possibly its history; - the "originating context" is a context which represents some intended starting point that you might look at first. -We might continue to articulate further types of contexts, but the general pattern that emerges is that a context exists to form a purposeful grouping, regardless of the specific purpose. For example, if we had the notion of a conversation, then we might reasonably say that someone owns this conversation and can apply their authority to it. Looking at some object or activity within this context is generally not recommended on its own; it is better to view the entire conversation or some page of it rather than viewing a singular message. +We might continue to articulate further types of contexts, but the general pattern that emerges is that a context exists to form a purposeful grouping, regardless of the specific purpose. For example, if we had the notion of a conversation, then we might reasonably say that someone owns this conversation and can apply their authority to it. Looking at some object or activity within this context is generally not recommended on its own; it is better to view the entire conversation or some page of it rather than viewing a singular object. ## Sample workflows and use-cases involving context @@ -55,7 +55,7 @@ The context may be presented using the following abstractions: Contexts may be nested within other contexts: - A forum topic/thread may be nested in a "forum" or "forum category", and may be nested in another parent forum as a sub-forum. -- A "wall" on a profile or group may contain conversations, which in turn may contain the top-level object and its comments +- A "wall" on a social networking profile may contain conversations, which in turn contain the posts/comments - A "guild" or "space" may contain multiple chat rooms with a common audience It is also possible to *not* have a context. Such objects exist only in the general context of their author (via `attributedTo`) and are otherwise self-sufficient. This can include: @@ -66,14 +66,14 @@ It is also possible to *not* have a context. Such objects exist only in the gene ## A normative description of the context property -The use of `context` SHOULD adhere to the following guidelines: +The use of `context` might adhere to the following guidelines: - The `context` SHOULD have a purpose. Consider tags for looser references. -- The `context` SHOULD be resolvable. The resolved object or link should describe the context with at least the additional information needed to fully process the activity or object. - - The resolved `context` SHOULD be a Collection or a subtype. This Collection SHOULD contain the related items. - - The `context` MAY require authorization to resolve properly or fully, but SHOULD include an `attributedTo` property at minimum. +- The `context` SHOULD be resolvable. The resolved object or link can describe the context with at least the additional information needed to fully process the activity or object. + - The `context` MAY require authorization to resolve properly or fully, but SHOULD include an `attributedTo` property at minimum which denotes the authority for that context. + - The resolved `context` SHOULD be a Collection or a subtype. This Collection can contain the related items. -When encountering an object with a `context`: +When encountering an object with a `context` and choosing to author your own object: - You MAY copy the `context` as-is, if you wish for your object to be included in the same context. - You MAY set your own `context`, if you wish for your object to be in a separate context owned by you. @@ -81,7 +81,7 @@ When encountering an object with a `context`: In cases where you copy a context owned by someone else, you SHOULD send your activity to the owner of that context, defined via `context.attributedTo` if resolvable. You SHOULD NOT send your activity to anyone else, unless you implement a mechanism to allow third-party observers to verify that your object or activity is indeed a valid member of the referenced context. (A further FEP may follow up on this topic.) -Upon receipt of such an activity referencing a context owned by you, you SHOULD distribute the object to the audience of the context, specified by `context.audience`, and possibly including `context.followers` if the context is itself an actor. 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.) You MAY drop certain activities not matching specific policies; for example, you might filter out spam, or implement a policy such that only certain actors (members, participants, etc.) are allowed to be included in the context. (Signaling which actors can participate is out-of-scope for this FEP and may be covered in a further FEP.) +Upon receipt of such an activity referencing a context owned by you, you SHOULD distribute the object to the audience of the context, specified by `context.audience`, and possibly including `context.followers` if the context is itself an actor. This may be done with inbox forwarding or by delivering an Add activity. (Verification mechanisms for inbox forwarding or Adding private objects is out-of-scope for this FEP.) You MAY drop certain activities not matching specific policies; for example, you might filter out spam, or implement a policy such that only certain actors (members, participants, etc.) are allowed to be included in the context. (Signaling which actors can participate is out-of-scope for this FEP and may be covered in a further FEP.) In cases where you copy an unresolvable context, or a context without an owner, you may deliver to an arbitrary audience as if there were no context. However, this is not recommended. Actors that receive such an activity or object with an unverifiable context SHOULD ignore this context, and SHOULD NOT associate the object with the declared context. @@ -93,6 +93,91 @@ Because [PUB] does not define the use of `context` as a property, it is up to Ac 2. Create the `Object` and specify the `context` as the `id` obtained in step 1. Set an appropriate `audience` or use `to`/`cc` to deliver the Create activity as-is. Save the returned Object or its `id` to be used in the next step. 3. Add the `Object` to the context `Collection`, using the response from step 2. You may wish to deliver this Add activity `to`/`cc` your intended recipients, especially if you did not deliver the Create Object from step 2. +### Examples + +(This section is non-normative.) + +#### Example 1: A minimal example for participating in a context + +You encounter the following object: + +```json +{ + "@context": "https://www.w3.org/ns/activitystreams", + "id": "https://example.com/some-object", + "context": "https://example.com/some-context", + "content": "Hello world" +} +``` + +You wish to participate in the context, so you GET the context: + +```json +{ + "@context": "https://www.w3.org/ns/activitystreams", + "id": "https://example.com/some-context", + "attributedTo": "https://example.com/context-owner", + "audience": "https://example.com/context-audience", + "type": "Collection", + "orderedItems": ["https://example.com/some-object"] +} +``` + +You send your message to the context authority only, while copying their context: + +```json +{ + "@context": "https://www.w3.org/ns/activitystreams", + "id": "https://example.com/your-activity", + "audience": "https://example.com/context-owner", + "actor": "https://example.com/you", + "type": "Create", + "object": { + "id": "https://example.com/your-object", + "context": "https://example.com/some-context", + "content": "Hello!" + } +} +``` + +The context authority then adds your object or message to the context: + +```json +{ + "@context": "https://www.w3.org/ns/activitystreams", + "id": "https://example.com/their-activity", + "audience": [ + "https://example.com/context-owner-followers", + "https://example.com/context-audience", + "https://example.com/you", // to keep you in the loop + "https://example.com/your-followers" // for inbox forwarding + ], + "actor": "https://example.com/context-owner", + "type": "Add", + "object": "https://example.com/your-object", + "target": "https://example.com/some-context" +} +``` + +The resulting state of the context collection is now like so: + +```json +{ + "@context": "https://www.w3.org/ns/activitystreams", + "id": "https://example.com/some-context", + "attributedTo": "https://example.com/context-owner", + "type": "Collection", + "orderedItems": [ + "https://example.com/some-object", + "https://example.com/your-object" + ] +} +``` + +Third-party observers (such as members of `https://example.com/context-audience`) can validate the Add activity by using the following checks: + +- `Add.actor` == `context.attributedTo` (the actor is allowed to modify a collection that they own) + ## References - [VOCAB] James M Snell, Evan Prodromou, [Activity Vocabulary](https://www.w3.org/TR/activitypub/), 2018