1
0
mirror of https://codeberg.org/fediverse/fep.git synced 2026-08-05 11:46:04 +00:00

7888: Clarify normative text, add more examples, fix references

This commit is contained in:
a
2024-11-04 21:53:38 -06:00
parent f96a951449
commit faaea6e612
+294 -45
View File
@@ -69,22 +69,38 @@ It is also possible to *not* have a context. Such objects exist only in the gene
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 can describe the context with at least the additional information needed to fully process the activity or object.
- A `context` SHOULD have a purpose; consider tags for looser references.
- Objects sharing a certain `context` SHOULD be strongly related and intended to be viewed in the same grouping.
- A `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.
- The resolved `context` SHOULD be a Collection or a subtype. This collection can contain the related items.
When encountering an object with a `context` and choosing to author your own object:
When encountering an object with a `context` as a consumer or browser:
- You MAY copy the `context` as-is, if you wish for your object to be included in the same context.
- If a `context` is a resolvable collection, then you SHOULD generally view the collection instead of viewing that object independently.
- You MUST NOT assume that an object is included as an item in the collection without proof of its inclusion. Clients that receive an activity or object with an unverifiable context SHOULD either ignore this context (and SHOULD NOT associate the object with the declared context), or otherwise SHOULD indicate to users that the context is unverified.
- Criteria for establishing proof of inclusion in a collection is out of scope of this FEP, but MAY include:
- Viewing the collection directly and encountering the object as a collection item.
- Querying the collection via some querying mechanism that allows determining if an object is included in a collection.
- Having knowledge that the object was Added to the collection in question, without knowledge of a subsequent Remove.
When encountering an object with a `context` and choosing to author your own object or activity that interacts with it:
- You MAY copy a `context` as-is, if you wish for your object to be included in that same context.
- If you do this, you SHOULD send your activity to the owner(s) of the context(s), defined via `context.attributedTo` if resolvable.
- You MAY set your own `context`, if you wish for your object to be in a separate context owned by you.
- You MAY remove the `context` entirely, if you wish for your object to exist on its own.
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 an activity where a `context` is owned by you, or where the activity's `object` has a `context` owned by you:
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.
- You SHOULD distribute the object or activity that declares your `context` to the audience of that context.
- The audience of the context MAY be possibly specified by `context.audience`, and MAY possibly include `context.followers` if the context is itself an actor.
- Distribution to the audience of the context MAY be done by the following mechanisms:
- Inbox forwarding. If the object or activity to be distributed addresses `context.audience` and/or `context.followers` as collections, then inbox forwarding the activity MAY suffice to notify interested actors about the new activity or object.
- Add activity. To properly manage the context collection's state (when the context is a collection), the context owner SHOULD locally Add the appropriate object or activity to the collection. This Add activity MAY also be delivered over ActivityPub S2S while addressing the `context.audience` and/or `context.followers` as recipients, serving as a notification that the object or activity was included in the context collection by the context owner.
- Other mechanisms. It is possible that the software managing a context collection may use other protocols or activity-forms to distribute relevant objects or activities. Non-normative examples include Announce or potential extension activity types.
- 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.)
- (Verification mechanisms for inbox forwarding or Adding private objects is out-of-scope for this FEP.)
### Creating and maintaining contexts using ActivityPub C2S
@@ -105,58 +121,62 @@ 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"
"id": "https://domain.example/some-object",
"context": "https://domain.example/some-context",
"content": "Hello world",
"summary": "<some-object> exists in <some-context> and has content saying \"Hello world\"."
}
```
You wish to participate in the context, so you GET the context:
You wish to participate in the context, so you dereference 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"]
"id": "https://domain.example/some-context",
"attributedTo": "https://domain.example/context-owner",
"audience": "https://domain.example/context-audience",
"type": "OrderedCollection",
"orderedItems": ["https://domain.example/some-object"],
"summary": "<some-context> is an OrderedCollection owned by <context-owner> and with an audience of <context-audience>. It currently contains <some-object>."
}
```
You send your message to the context authority only, while copying their context:
You send your message to the context authority, 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",
"id": "https://domain.example/your-activity",
"actor": "https://domain.example/you",
"type": "Create",
"object": {
"id": "https://example.com/your-object",
"context": "https://example.com/some-context",
"id": "https://domain.example/your-object",
"context": "https://domain.example/some-context",
"content": "Hello!"
}
},
"audience": ["https://domain.example/context-owner", "https://domain.example/context-audience"],
"summary": "<you> Created <your-object> in <some-context>, and are delivering this activity addressing <context-owner> and <context-audience>."
}
```
The context authority then adds your object or message to the context:
The context authority then might forward this activity to the context audience. The context authority also might add 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",
"id": "https://domain.example/their-activity",
"actor": "https://domain.example/context-owner",
"type": "Add",
"object": "https://example.com/your-object",
"target": "https://example.com/some-context"
"object": "https://domain.example/your-object",
"target": "https://domain.example/some-context",
"audience": [
"https://domain.example/context-owner-followers",
"https://domain.example/context-audience",
"https://domain.example/you", // to keep you in the loop
"https://domain.example/your-followers" // for inbox forwarding
],
"summary": "The <context-owner> Added <your-object> to <some-context>, and are delivering this activity addressing their followers, the <context-audience>, <you>, and <your-followers>."
}
```
@@ -165,24 +185,253 @@ 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",
"id": "https://domain.example/some-context",
"attributedTo": "https://domain.example/context-owner",
"type": "OrderedCollection",
"orderedItems": [
"https://example.com/some-object",
"https://example.com/your-object"
]
"https://domain.example/some-object",
"https://domain.example/your-object"
],
"summary": "<some-context> now contains <some-object> and <your-object> after the latter has been Added to the OrderedCollection by <context-owner>."
}
```
Third-party observers (such as members of `https://example.com/context-audience`) can validate the Add activity by using the following checks:
Third-party observers (such as members of `https://domain.example/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)
#### Example 2: Choosing not to participate in the same context
You encounter the following object:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/some-object",
"context": "https://domain.example/some-context",
"content": "Hello world",
"summary": "<some-object> exists in <some-context> and has content saying \"Hello world\"."
}
```
You want to establish your own context, separately from the current object's context, so you create your own context:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/creating-a-different-context",
"actor": "https://domain.example/you",
"type": "Create",
"object": {
"id": "https://domain.example/a-different-context",
"type": "OrderedCollection",
"attributedTo": "https://domain.example/you"
},
"summary": "<you> Created <a-different-context>, which is an OrderedCollection."
}
```
You can now set this new context on your interaction, with the intent that your interaction is shown in a separate grouping from the original object:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/creating-a-post-in-a-different-context",
"actor": "https://domain.example/you",
"type": "Create",
"object": {
"id": "https://domain.example/a-post-in-a-different-context",
"content": "Starting a new thread to say \"Hello World\" in a different context.",
"inReplyTo": {
"id": "https://domain.example/some-object",
"context": "https://domain.example/some-context",
"content": "Hello world",
"summary": "<some-object> exists in <some-context> and has content saying \"Hello world\"."
},
"context": "https://domain.example/a-different-context"
},
"summary": "<you> Created <a-post-in-a-different-context> which is inReplyTo <some-object> in <some-context>, but your object is in <a-different-context>."
}
```
You add your object to your own context:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/their-activity",
"actor": "https://domain.example/you",
"type": "Add",
"object": "https://domain.example/a-post-in-a-different-context",
"target": "https://domain.example/a-different-context",
"summary": "<you> Added <a-post-in-a-different-context> to <a-different-context>."
}
```
The original object's context is unchanged:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/some-context",
"type": "OrderedCollection",
"attributedTo": "https://domain.example/context-owner",
"audience": "https://domain.example/context-audience",
"orderedItems": ["https://domain.example/some-object"],
"summary": "<some-context> is an OrderedCollection owned by <context-owner> and with an audience of <some-object>. It currently contains <some-object>."
}
```
Your context now looks like this:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/a-different-context",
"type": "OrderedCollection",
"attributedTo": "https://domain.example/you",
"orderedItems": ["https://domain.example/a-post-in-a-different-context"],
"summary": "<a-different-context> is an OrderedCollection owned by <you>. It currently contains <a-post-in-a-different-context>."
}
```
#### Example 3: Encountering multiple contexts
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/some-object",
"context": ["https://domain.example/some-context", "https://domain.example/some-other-context"]
"content": "Hello world",
"summary": "<some-object> exists in <some-context> and <some-other-context> and has content saying \"Hello world\"."
}
```
You dereference the two contexts:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/some-context",
"attributedTo": "https://domain.example/context-owner",
"type": "OrderedCollection",
"orderedItems": ["https://domain.example/some-object"],
"summary": "<some-context> is an OrderedCollection owned by <context-owner>. It currently contains <some-object>."
}
```
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/some-other-context",
"attributedTo": "https://domain.example/other-context-owner",
"type": "OrderedCollection",
"orderedItems": ["https://domain.example/some-object"],
"summary": "<some-other-context> is an OrderedCollection owned by <other-context-owner>. It currently contains <some-object>."
}
```
You can now choose to participate in either context, both contexts, a different context, or no context.
To participate in both contexts:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/your-activity",
"actor": "https://domain.example/you",
"type": "Create",
"object": {
"id": "https://domain.example/your-object",
"context": ["https://domain.example/some-context", "https://domain.example/some-other-context"],
"content": "Hello!"
},
"audience": ["https://domain.example/context-owner", "https://domain.example/other-context-owner"],
"summary": "<you> Created <your-object> in <some-context> and <some-other-context>, and are delivering this activity addressing <context-owner> and <other-context-owner>."
}
```
It may be that you are refused addition into some context, but granted addition into some other context:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/context-1-activity",
"actor": "https://domain.example/context-owner",
"type": "Reject",
"object": "https://domain.example/your-activity",
"summary": "<context-owner> Rejected <your-activity>.",
"content": "Sorry, I don't want to add your object to my context."
}
```
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/context-2-activity",
"actor": "https://domain.example/other-context-owner",
"type": "Add",
"object": "https://domain.example/your-object",
"target": "https://domain.example/some-other-context",
"summary": "<other-context-owner> Added <your-object> to <some-other-context>."
}
```
A third-party observer encounters your object:
```json
{
"id": "https://domain.example/your-object",
"context": ["https://domain.example/some-context", "https://domain.example/some-other-context"],
"content": "Hello!"
}
```
They attempt to verify that your object is included in the first context, and find that it is not included:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/some-context",
"attributedTo": "https://domain.example/context-owner",
"type": "OrderedCollection",
"orderedItems": ["https://domain.example/some-object"],
"summary": "<some-context> is an OrderedCollection owned by <context-owner>. It currently contains <some-object>."
}
```
The third-party observer attempts to verify that your object is included in the second context, and finds that it is included:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://domain.example/some-other-context",
"attributedTo": "https://domain.example/other-context-owner",
"type": "OrderedCollection",
"orderedItems": ["https://domain.example/some-object", "https://domain.example/your-object"],
"summary": "<some-other-context> is an OrderedCollection owned by <other-context-owner>. It currently contains <some-object> and <your-object>."
}
```
The third-party observer's client renders your object as unverifiably within some context, and verifiably within some other context.
```text
<you> Created <your-object>
<your-object> has content: "Hello!"
<your-object> is part of the following contexts:
- <some-context> (❓ unverified)
- <some-other-context> (✅ verified)
```
The third-party observer may then choose to navigate to (and possibly participate in) the latter context.
## References
- [VOCAB] James M Snell, Evan Prodromou, [Activity Vocabulary](https://www.w3.org/TR/activitypub/), 2018
- [PUB] Christine Lemmer Webber, Jessica Tallon, [ActivityPub](https://www.w3.org/TR/activitypub/), 2018
- [VOCAB] James M Snell, Evan Prodromou, [Activity Vocabulary][VOCAB], 2017
- [PUB] Christine Lemmer Webber, Jessica Tallon, [ActivityPub][PUB], 2018
[PUB]: https://www.w3.org/TR/activitypub/
[VOCAB]: https://www.w3.org/TR/activitystreams-vocabulary/
## Copyright