The actor layer
Note
bovine_herd will probably be adapted to fit this role. The big change will actually to remove stuff like storing activities … So this layer exists, except it currently does too much.
The cattle_grid layer checks remote identities. With the exception of signed objects, e.g. eddsa-jcs-2022, cattle_grid should be the one time public keys of remote actors are retrieved.
The goal of the next layer should be to enable to send messages. This is already sufficiently complicated to make a lot of stuff necessary. See jskitten for a simple implementation.
Plan
My current plan for the next layer are the following things:
- The actor objects
- The inbox endpoint
- The ability to send messages
- The followers collection (can be disabled)
- The following collection (can be disabled)
- Necessary parsing / validation / modifications
These things are connected and in some sense not separable.
graph LR
A[send messages] -->|needs| B[followers collection]
A -->|needs| C[private key]
C -->|defines| D[public key]
D -->|distributed by| E[actor object]
B -->|update from| F[Accept-Follow to Inbox]
This shows that in order to be able to send messages, we need most of the properties already mentioned. I believe that if we update the actor object, e.g. change the public key, it should be best practice to update at least the followers and following. So this makes tracking the following collection also necessary.
Note
If one doesn’t support the followers collection, everything becomes simpler. Unfortunately, it also becomes uninteresting, as the followers collection is one of the things that turn the Fediverse into a social network. More interesting would be to support other addressing collections.
Things that can be build with this
Without needing fancy storage:
- Bots like jskitten that reply to a prompt
- RSS to Fedi bots, e.g. fetch an RSS feed and on updates post them
- Better lists like ayrshire
- Tag reposters like tags
With fancy storage: anything. That’s not really the point, this reduces building something for the Fediverse to implementing logic to store your own content and make it accessible. You do not have to worry about handling POST requests, except by communicating with queues.
Actor object
The actor object contains the following properties, we are interested in
{
"@context": [...],
"id": "https://my_server.example/my_actor",
"inbox": "https://my_server.example/my_inbox",
"followers": "https://my_server.example/my_followers",
"following": "https://my_server.example/my_followers",
"publicKey": {
"id": "https://my_server.example/my_actor#key",
"owner": "https://my_server.example/my_actor",
"publicKeyPem": "..."
}, ...
}
we probably also want to manage the preferredUsername
and webfinger here,
as the current Fediverse is unusable without it. Similarly, one might want
to define an outbox
, as people seem to expect it (it’s a MUST in ActivityPub
for some reason).
If no outbox service is provided, one can just stub it to direct to the actor or something.
outbox service
This means one probably wants some server to play the role of outbox … One should consider the outbox service as a challenge of writing the simplest code. It just needs to subscribe to the send queue, filter out non-public things, then store ids (keep say the last 1000). Then vomit them out as an OrderedCollection on requests.
Sending messages
Sending messages involves several steps:
- Determine the recipients by dereferencing collections owned by the actor, i.e. the followers collection
- Remove
bto
andbcc
, then enqueue delivery for each recipient - Transform messages to ActivityPub format
- Lookup inbox for recipient
- Send signed post to recipient’s inbox with message sans
bto
,bcc
One should of course cache the looked up inboxes, and update them on
an Update
.
Due to Json-LD and ActivityPub being great, one needs to compact the activities against the context
to be interoperable with a lot of software. More @context
elements may be necessary.
So one probably needs to cook up some way to transport this.
Followers / Following
One should introduce the following meaning to the absence of followers / following collections:
- If no followers collection, the actor does not process
Follow
requests. - If no following collection, the actor does not send
Follow
requests.
Objects are added to these collections on Accept - Follow
and removed on
Undo - Follow
, Reject - Follow
, Block
, Delete
, Undo - Accept - Follow
.
Finally, modifications of the entry may occur on Update
and Move
.
Parsing / Validation / Modifications
The first step in parsing should be getting rid of external json-ld contexts. One can probably just use compacted against the empty context. Next, one should check that the ids match the authority associated with the requester. This falls under validation. If the authority does not match, one should check for signatures (keep the raw message), otherwise refetch the stuff.
By modifications, I mean stuff like handling Accepts
. Finally, one needs
to include inbox forwarding.