mirror of
https://codeberg.org/fediverse/fep.git
synced 2026-08-05 03:35:52 +00:00
FEP 4ccd update (#640)
There are a few updates in this PR. - Two new inverse properties, `pendingFollowersOf` and `pendingFollowingOf` - Semantically versioned aliases for the context for future-proofing - One section per term - Implementations list - Clarified examples Reviewed-on: https://codeberg.org/fediverse/fep/pulls/640 Co-authored-by: Evan Prodromou <codeberg@evanprodromou.name> Co-committed-by: Evan Prodromou <codeberg@evanprodromou.name>
This commit is contained in:
committed by
silverpill
parent
6a071aa907
commit
d791010e42
@@ -0,0 +1,125 @@
|
||||
<mxfile host="Electron" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
|
||||
<diagram name="Page-1" id="c1nq6VIKBeCJtnm8D7El">
|
||||
<mxGraphModel dx="1674" dy="778" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-63" value="" style="html=1;align=center;verticalAlign=top;rounded=1;absoluteArcSize=1;arcSize=127;dashed=0;whiteSpace=wrap;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="348" y="860" width="279" height="280" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-65" value="" style="html=1;align=center;verticalAlign=top;rounded=1;absoluteArcSize=1;arcSize=127;dashed=0;whiteSpace=wrap;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="489" y="730" width="279" height="280" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-61" value="" style="html=1;align=center;verticalAlign=top;rounded=1;absoluteArcSize=1;arcSize=127;dashed=0;whiteSpace=wrap;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="348" y="570" width="279" height="280" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-64" value="" style="html=1;align=center;verticalAlign=top;rounded=1;absoluteArcSize=1;arcSize=127;dashed=0;whiteSpace=wrap;fillColor=none;shadow=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="200" y="730" width="279" height="280" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;curved=1;" parent="1" source="4ccpedBz1mQfKb1iKG4l-32" target="4ccpedBz1mQfKb1iKG4l-43" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="500" y="780" />
|
||||
<mxPoint x="500" y="630" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-48" value="Client<br>Undo" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="4ccpedBz1mQfKb1iKG4l-44" vertex="1" connectable="0">
|
||||
<mxGeometry x="0.0595" y="-3" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-50" style="edgeStyle=orthogonalEdgeStyle;curved=1;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="4ccpedBz1mQfKb1iKG4l-32" target="4ccpedBz1mQfKb1iKG4l-49" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-55" value="Client Accept" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="4ccpedBz1mQfKb1iKG4l-50" vertex="1" connectable="0">
|
||||
<mxGeometry x="-0.2308" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="1" y="-1" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-52" style="edgeStyle=orthogonalEdgeStyle;curved=1;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="4ccpedBz1mQfKb1iKG4l-32" target="4ccpedBz1mQfKb1iKG4l-40" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-56" value="Client<br>Reject" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="4ccpedBz1mQfKb1iKG4l-52" vertex="1" connectable="0">
|
||||
<mxGeometry x="-0.2583" y="7" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-32" value="Both<br>Pending" style="html=1;align=center;verticalAlign=top;rounded=1;absoluteArcSize=1;arcSize=10;dashed=0;whiteSpace=wrap;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="380" y="750" width="60" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-35" value="Both Connected" style="html=1;align=center;verticalAlign=top;rounded=1;absoluteArcSize=1;arcSize=10;dashed=0;whiteSpace=wrap;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="520" y="910" width="70" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-41" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;" parent="1" source="4ccpedBz1mQfKb1iKG4l-36" target="4ccpedBz1mQfKb1iKG4l-40" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="220" y="660" />
|
||||
<mxPoint x="220" y="910" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-46" value="Client<br>Follow" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="4ccpedBz1mQfKb1iKG4l-41" vertex="1" connectable="0">
|
||||
<mxGeometry x="-0.0309" relative="1" as="geometry">
|
||||
<mxPoint y="-61" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-36" value="No Connection" style="html=1;align=center;verticalAlign=top;rounded=1;absoluteArcSize=1;arcSize=10;dashed=0;whiteSpace=wrap;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="640" width="60" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-53" style="edgeStyle=orthogonalEdgeStyle;curved=1;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="4ccpedBz1mQfKb1iKG4l-40" target="4ccpedBz1mQfKb1iKG4l-36" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-59" value="Server Reject" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="4ccpedBz1mQfKb1iKG4l-53" vertex="1" connectable="0">
|
||||
<mxGeometry x="0.4072" y="-6" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="9kQQHvmXede9cpbBGcYE-1" value="Server Follow" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.75;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="4ccpedBz1mQfKb1iKG4l-40" target="4ccpedBz1mQfKb1iKG4l-32">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-40" value="A1Only Pending" style="html=1;align=center;verticalAlign=top;rounded=1;absoluteArcSize=1;arcSize=10;dashed=0;whiteSpace=wrap;" parent="1" vertex="1">
|
||||
<mxGeometry x="240" y="880" width="61" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-45" value="Server Undo" style="edgeStyle=orthogonalEdgeStyle;curved=1;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" parent="1" source="4ccpedBz1mQfKb1iKG4l-43" target="4ccpedBz1mQfKb1iKG4l-36" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-43" value="A2&nbsp; Only Pending" style="html=1;align=center;verticalAlign=top;rounded=1;absoluteArcSize=1;arcSize=10;dashed=0;whiteSpace=wrap;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="370" y="610" width="70" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-51" style="edgeStyle=orthogonalEdgeStyle;curved=1;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="4ccpedBz1mQfKb1iKG4l-49" target="4ccpedBz1mQfKb1iKG4l-35" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-54" value="Server Accept" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="4ccpedBz1mQfKb1iKG4l-51" vertex="1" connectable="0">
|
||||
<mxGeometry x="-0.1622" y="4" relative="1" as="geometry">
|
||||
<mxPoint x="18" y="4" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-66" value="" style="edgeStyle=orthogonalEdgeStyle;curved=1;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="4ccpedBz1mQfKb1iKG4l-49" target="4ccpedBz1mQfKb1iKG4l-32" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-49" value="A2 Only Connnected" style="html=1;align=center;verticalAlign=top;rounded=1;absoluteArcSize=1;arcSize=10;dashed=0;whiteSpace=wrap;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="375" y="910" width="70" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-58" style="edgeStyle=orthogonalEdgeStyle;curved=1;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=0;entryDx=0;entryDy=0;" parent="1" source="4ccpedBz1mQfKb1iKG4l-57" target="4ccpedBz1mQfKb1iKG4l-36" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-57" value="" style="ellipse;fillColor=strokeColor;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="80" y="570" width="30" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-67" value="A1 in A2.followers" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="440" y="1090" width="112" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-68" value="A2 in A1.following" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="640" y="740" width="112" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-69" value="Activity in A2.pendingFollowers" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="480" y="590" width="112" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4ccpedBz1mQfKb1iKG4l-70" value="Activity in A1.pendingFollowing" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="230" y="960" width="112" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
+138
-29
@@ -4,13 +4,13 @@ authors: Evan Prodromou <evan@prodromou.name>
|
||||
status: DRAFT
|
||||
dateReceived: 2023-06-21
|
||||
trackingIssue: https://codeberg.org/fediverse/fep/issues/129
|
||||
discussionsTo: https://codeberg.org/fediverse/fep/issues/129
|
||||
discussionsTo: https://codeberg.org/evanp/fep/issues
|
||||
---
|
||||
# FEP-4ccd: Pending Followers Collection and Pending Following Collection
|
||||
|
||||
## Summary
|
||||
|
||||
This specification defines two collections, `pendingFollowers` and `pendingFollowing`, with which users can review and manage their pending follow requests.
|
||||
This ActivityPub extension defines two collections, `pendingFollowers` and `pendingFollowing`, with which users can review and manage their pending follow requests.
|
||||
|
||||
## Motivation
|
||||
|
||||
@@ -24,27 +24,13 @@ The new `pendingFollowing` collection can be used to review outgoing `Follow` ac
|
||||
|
||||
Because the full activity data is needed to `Accept`, `Reject` or `Undo`, these collections should include `Follow` activities, and not just the actors requesting to follow.
|
||||
|
||||
## Details
|
||||
|
||||
`pendingFollowers` is a property of an actor. It is a collection of `Follow` activities that have been sent **to** the actor, but not yet been accepted or rejected.
|
||||
|
||||
`pendingFollowing` is a property of an actor. It is a collection of `Follow` activities that have been sent **by** the actor, but not yet been accepted or rejected.
|
||||
|
||||
Both properties MUST be an `OrderedCollection` or `Collection`. Items in the collection MUST be in reverse chronological order.
|
||||
|
||||
Items in the collections MUST be `Follow` activities. They MUST be unique by `id`.
|
||||
|
||||
Each `object` of a `Follow` activity in the `pendingFollowing` collection MUST be unique by `id`.
|
||||
|
||||
Each `actor` of a `Follow` activity in the `pendingFollowers` collection MUST be unique by `id`.
|
||||
|
||||
When an `Accept`, `Reject`, or `Undo` activity with a `Follow` activity as `object` is processed, that `Follow` activity MUST NOT be included in the `pendingFollowers` and `pendingFollowing` collections in the future.
|
||||
Note that this extension is primarily useful for clients and servers that implement the ActivityPub API. Furthermore, it is primarily useful for actors that manually approve followers. The [manuallyApprovesFollowers](https://swicg.github.io/miscellany#manuallyApprovesFollowers) property in the [ActivityPub Miscellaneous Terms][miscellany] can be used to indicate that an actor manually approves followers.
|
||||
|
||||
## Context
|
||||
|
||||
The context document for this specification is `https://purl.archive.org/socialweb/pending`. Its contents are as follows:
|
||||
The context document for this ActivityPub extension is at `https://purl.archive.org/socialweb/pending`. Its contents are as follows:
|
||||
|
||||
```
|
||||
```json
|
||||
{
|
||||
"@context": {
|
||||
"pdg": "https://purl.archive.org/socialweb/pending#",
|
||||
@@ -55,20 +41,85 @@ The context document for this specification is `https://purl.archive.org/socialw
|
||||
"pendingFollowing": {
|
||||
"@id": "pdg:pendingFollowing",
|
||||
"@type": "@id"
|
||||
},
|
||||
"pendingFollowersOf": {
|
||||
"@id": "pdg:pendingFollowersOf",
|
||||
"@type": "@id"
|
||||
},
|
||||
"pendingFollowingOf": {
|
||||
"@id": "pdg:pendingFollowingOf",
|
||||
"@type": "@id"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Semantic versioning
|
||||
|
||||
For compatibility, the context document for this extension has aliases using [semantic versioning][semver].
|
||||
|
||||
- `https://purl.archive.org/socialweb/pending/1.1.0`. This version is immutable.
|
||||
- `https://purl.archive.org/socialweb/pending/1.1`. This version may be updated with bug fixes, documentation, or minor changes, but no new terms.
|
||||
- `https://purl.archive.org/socialweb/pending/1`. This version may be updated with bug fixes or minor changes, and may include new terms, but will not include breaking changes.
|
||||
- `https://purl.archive.org/socialweb/pending`. This version may be updated with bug fixes or minor changes, may include new terms, and may include breaking changes. It is the latest version of the context document.
|
||||
|
||||
All terms in the context document use the same namespace, `https://purl.archive.org/socialweb/pending#`.
|
||||
|
||||
## Properties
|
||||
|
||||
As with other ActivityPub properties, the values of these properties can be included by a reference URL, or by an [embedded node object](https://www.w3.org/TR/json-ld11/#embedding).
|
||||
|
||||
### `pendingFollowers`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| URI | `https://purl.archive.org/socialweb/pending#pendingFollowers` |
|
||||
| Notes | `pendingFollowers` is a collection of `Follow` activities that have been sent **to** the actor, but have not yet been accepted or rejected. Items in the collection MUST be in reverse chronological order. Items in the collections MUST be `Follow` activities. They MUST be unique by `id`. Each `actor` of a `Follow` activity in the collection MUST be unique by `id`. |
|
||||
| Domain | Object (ActivityPub actor) |
|
||||
| Range | `OrderedCollection` or `Collection` |
|
||||
| Functional | Yes |
|
||||
|
||||
### `pendingFollowing`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| URI | `https://purl.archive.org/socialweb/pending#pendingFollowing` |
|
||||
| Notes | `pendingFollowing` is a property of an actor. It is a collection of `Follow` activities that have been sent **by** the actor, but have not yet been accepted or rejected. They MUST be unique by `id`. Each `object` of a `Follow` activity in the collection MUST be unique by `id`.|
|
||||
| Domain | Object (ActivityPub actor) |
|
||||
| Range | `OrderedCollection` or `Collection` |
|
||||
| Functional | Yes |
|
||||
|
||||
### `pendingFollowersOf`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| URI | `https://purl.archive.org/socialweb/pending#pendingFollowersOf` |
|
||||
| Notes | This property identifies the actor for which the specified collection is the `pendingFollowers` collection. It is an inverse property of `pendingFollowers`. |
|
||||
| Domain | `Collection` or `OrderedCollection` |
|
||||
| Range | Object (ActivityPub actor) |
|
||||
| Functional | Yes |
|
||||
|
||||
### `pendingFollowingOf`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| URI | `https://purl.archive.org/socialweb/pending#pendingFollowingOf` |
|
||||
| Notes | This property identifies the actor for which the specified collection is the `pendingFollowing` collection. It is an inverse property of `pendingFollowing`. |
|
||||
| Domain | `Collection` or `OrderedCollection` |
|
||||
| Range | Object (ActivityPub actor) |
|
||||
| Functional | Yes |
|
||||
|
||||
## Examples
|
||||
|
||||
A publisher can include the `pendingFollowers` and `pendingFollowing` collection in the properties of an actor.
|
||||
|
||||
```
|
||||
### Actor with `pendingFollowers` and `pendingFollowing`
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://purl.archive.org/socialweb/pending"
|
||||
"https://purl.archive.org/socialweb/pending/1"
|
||||
],
|
||||
"id": "https://example.com/evanp",
|
||||
"type": "Person",
|
||||
@@ -79,21 +130,34 @@ A publisher can include the `pendingFollowers` and `pendingFollowing` collection
|
||||
"followers": "https://example.com/evanp/followers",
|
||||
"liked": "https://example.com/evanp/liked",
|
||||
"pendingFollowers": "https://example.com/evanp/pendingFollowers",
|
||||
"pendingFollowing": "https://example.com/evanp/pendingFollowing"
|
||||
"pendingFollowing": {
|
||||
"id": "https://example.com/evanp/pendingFollowing",
|
||||
"type": "Collection",
|
||||
"name": "Pending following for Evan Prodromou",
|
||||
"totalItems": 2
|
||||
},
|
||||
"manuallyApprovesFollowers": true,
|
||||
"to": ["as:Public"]
|
||||
}
|
||||
```
|
||||
|
||||
Retrieving the `pendingFollowers` collection would show incoming follow requests
|
||||
Notice that the `pendingFollowers` property is a URL, while the `pendingFollowing` property is an embedded object with useful additional properties.
|
||||
|
||||
### `pendingFollowers` collection
|
||||
|
||||
Retrieving the `pendingFollowers` collection shows incoming follow requests
|
||||
for this actor.
|
||||
|
||||
```
|
||||
```json
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://purl.archive.org/socialweb/pending"
|
||||
"https://purl.archive.org/socialweb/pending/1"
|
||||
],
|
||||
"id": "https://example.com/evanp/pendingFollowers",
|
||||
"type": "OrderedCollection",
|
||||
"attributedTo": "https://example.com/evanp",
|
||||
"pendingFollowersOf": "https://example.com/evanp",
|
||||
"name": "Pending followers for Evan Prodromou",
|
||||
"orderedItems": [
|
||||
{
|
||||
@@ -106,6 +170,8 @@ for this actor.
|
||||
"type": "Person",
|
||||
"name": "Alyssa P. Hacker"
|
||||
},
|
||||
"to": "https://example.com/evanp",
|
||||
"cc": "as:Public",
|
||||
"published": "2023-06-21T12:00:00Z"
|
||||
},
|
||||
{
|
||||
@@ -117,6 +183,8 @@ for this actor.
|
||||
"type": "Application",
|
||||
"name": "Jokebot 3000"
|
||||
},
|
||||
"to": "https://example.com/evanp",
|
||||
"cc": "as:Public",
|
||||
"published": "2023-05-07T12:00:00Z"
|
||||
}
|
||||
]
|
||||
@@ -125,44 +193,74 @@ for this actor.
|
||||
|
||||
Note that the second, earlier `Follow` activity has a custom `type` property. Note also that the `object` of the `Follow` activities, which will be the same for every activity, is elided for clarity and space.
|
||||
|
||||
```
|
||||
### `pendingFollowing` collection
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://purl.archive.org/socialweb/pending",
|
||||
"https://purl.archive.org/socialweb/pending/1",
|
||||
{"sports": "https://sports.example/ns#"}
|
||||
],
|
||||
"id": "https://example.com/evanp/pendingFollowing",
|
||||
"type": "Collection",
|
||||
"attributedTo": "https://example.com/evanp",
|
||||
"pendingFollowingOf": "https://example.com/evanp",
|
||||
"name": "Pending following for Evan Prodromou",
|
||||
"items": [
|
||||
{
|
||||
"type": ["sports:Fan", "Follow"],
|
||||
"id": "https://example.com/evanp/fan/309",
|
||||
"summary": "Evan is a fan of Jimena",
|
||||
"actor": "https://example.com/evanp",
|
||||
"object": {
|
||||
"id": "https://tennis.example/jimena",
|
||||
"type": "Person",
|
||||
"name": "Jimena Suarez"
|
||||
},
|
||||
"to": "https://tennis.example/jimena",
|
||||
"cc": "as:Public",
|
||||
"published": "2023-04-19T12:00:00Z"
|
||||
},
|
||||
{
|
||||
"type": "Follow",
|
||||
"id": "https://example.net/evanp/follow/214",
|
||||
"summary": "Evan wants to follow Montreal Weather Updates",
|
||||
"actor": "https://example.com/evanp",
|
||||
"object": {
|
||||
"id": "https://weather.example/canada/quebec/montreal",
|
||||
"type": "Service",
|
||||
"name": "Montreal Weather Updates"
|
||||
},
|
||||
"to": "https://weather.example/canada/quebec/montreal",
|
||||
"cc": "as:Public",
|
||||
"published": "2023-02-11T12:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Note that the first `Follow` activity has a custom `type` property. Note also that the `actor` of the `Follow` activities, which will be the same for every activity, is elided for clarity and space. Finally, note that even though the collection's type is `Collection` and the items property is `items`, the activities still must be in reverse chronological order.
|
||||
Note that the first `Follow` activity has a custom `type` property. Also note that even though the collection's type is `Collection` and the items property is `items`, the activities still must be in reverse chronological order.
|
||||
|
||||
## Processing requirements
|
||||
|
||||
An actor that manually approves followers SHOULD include the `manuallyApprovesFollowers` property in their actor object, with a value of `true`. This indicates that the actor will review and approve or reject incoming follow requests.
|
||||
|
||||
When a server receives an otherwise valid `Follow` activity from a client, it SHOULD add that activity to the `pendingFollowing` collection of the sending actor. The server SHOULD also add the `Follow` activity to the `pendingFollowers` collection of the actor that is being followed, if the followed actor is on the same server.
|
||||
|
||||
When a server receives an otherwise valid `Follow` activity from another server, it SHOULD add that activity to the `pendingFollowers` collection of the followed actor.
|
||||
|
||||
When a server receives an `Accept` or `Reject` activity with a `Follow` activity as `object` from a client, it SHOULD remove that `Follow` activity from the `pendingFollowers` collection of the actor. The server SHOULD also remove the `Follow` activity from the `pendingFollowing` collection of the actor that initiated the follow, if the following actor is on the same server.
|
||||
|
||||
When a server receives an `Accept` or `Reject` activity with a `Follow` activity as `object` from another server, it SHOULD remove that `Follow` activity from the `pendingFollowing` collection of the receiving actor.
|
||||
|
||||
When a server receives an `Undo` activity with a `Follow` activity as `object` from a client, it SHOULD remove that `Follow` activity from the `pendingFollowing` collection of the actor that sent the `Follow`. It SHOULD also remove the `Follow` activity from the `pendingFollowers` collection of the actor that was followed, if the followed actor is on the same server.
|
||||
|
||||
When a server receives an `Undo` activity with a `Follow` activity as `object` from another server, it SHOULD remove that `Follow` activity from the `pendingFollowers` collection of the receiving actor.
|
||||
|
||||
The following [Harel statechart](https://www.sciencedirect.com/science/article/pii/0167642387900359) illustrates the state transitions for a `Follow` activity between actors A1 and A2. The states show which objects belong to which collections, and the transitions show when activities are received and processed via the client API and then the server federation protocol.
|
||||
|
||||

|
||||
|
||||
## Security considerations
|
||||
|
||||
@@ -173,9 +271,20 @@ Some services or actors do not forward `Reject` activities to the actor of a `Fo
|
||||
|
||||
For these reasons, publishers SHOULD NOT make the `pendingFollowers` and `pendingFollowing` collections visible to unauthenticated users. Publishers SHOULD NOT make the `pendingFollowers` and `pendingFollowing` collections visible to authenticated users who are not the actor.
|
||||
|
||||
## Implementations
|
||||
|
||||
- [onepage.pub](https://github.com/evanp/onepage.pub/) is a simple ActivityPub server that implements the `pendingFollowers` and `pendingFollowing` collections.
|
||||
- [ap](https://github.com/evanp/ap) is a command-line ActivityPub client. It has commands to list and manage the `pendingFollowers` and `pendingFollowing` collections.
|
||||
|
||||
## References
|
||||
|
||||
- [ActivityPub] Christine Lemmer Webber, Jessica Tallon, [ActivityPub](https://www.w3.org/TR/activitypub/), 2018
|
||||
- Christine Lemmer Webber, Jessica Tallon, [ActivityPub][ActivityPub], 2018
|
||||
- Evan Prodromou, [ActivityPub Miscellaneous Terms][miscellany], 2023
|
||||
- Tom Preston-Werner, [Semantic Versioning 2.0.0][semver], 2017
|
||||
|
||||
[ActivityPub]: https://www.w3.org/TR/activitypub/
|
||||
[semver]: https://semver.org/
|
||||
[miscellany]: https://swicg.github.io/miscellany/
|
||||
|
||||
## Copyright
|
||||
|
||||
|
||||
Reference in New Issue
Block a user