Confused about the (two types of?) Actor Objects

The Actor Object as described in the specification has an Inobx property that is a JSON file (a Collection, in this case), but when a server retrieves the Actor JSON-LD representation to find its inbox, I’m assuming it wants to find a URL path to post to. Something like this.
What is the Actor Object? Are there different types? Where should a remote server and/or a client find it?

JSON-LD objects can contain other objects either by their ID or by embedding the object. That ID is then the URL that should be POSTed to.

There are several types of Actor, the most common is Person. The AP spec doesn’t include any “discovery” path outside of receiving activities from the actor, but most implementations also implement WebFinger for this purpose

All other types are described in the Vocabulary Spec.

I don’t quite understand the other two answers given here, but the spec is assuming that the “inbox” url should be able to support both GET and POST in different contexts (see here for more on http methods).

In practice, GETing the inbox is only relevant when implementing the c2s section of the spec (so clients can retrieve the list of relevant activities from the server), and POSTing to the inbox is only relevant when implementing the s2s section of the spec (so servers can deliver activities to other servers that need to know about them). So, for example, because Mastodon only implements s2s, and not c2s, it only allows a POST to the inbox route, not a GET. You could imagine a corresponding c2s only ActivityPub server that allowed clients to GET their inboxes (and POST to their outboxes, to publish new activities), but didn’t implement federation.

Does that make sense? The important concept here is that the HTTP verb used (GET or POST) depends on the context of what you want to do with the resource on the other end.

What I don’t get is where and how the inbox URI should be presented.

The Actor Object in the specification declares the Actor’s Inbox as "inbox": "https://kenzoishii.example.com/inbox.json" – a Collection. Is a remote server supposed to HTTP POST to a JSON file?

Meanwhile the Actor Object in the blog post I linked declares the Actor’s Inbox as "inbox": "https://my-example.com/inbox" which makes a lot more sense. I was temporarily confused because I didn’t understand where a remote server would find this Actor Object (even though I implemented webfinger myself a few days ago… oh, well). That aside; why does this Actor Object differ so much from the Actor Object in the specification?

It might look different, but behind the scenes they’re all just HTTP servers responding to requests. Just because one has .json in it doesn’t mean that it’s a file, or the resource maps to a file under the hood.

I think this is maybe just a slightly-confusing example. Here’s another example from the same document (this one is Example 1):

{"@context": "https://www.w3.org/ns/activitystreams",
 "type": "Person",
 "id": "https://social.example/alyssa/",
 "name": "Alyssa P. Hacker",
 "preferredUsername": "alyssa",
 "summary": "Lisp enthusiast hailing from MIT",
 "inbox": "https://social.example/alyssa/inbox/",
 "outbox": "https://social.example/alyssa/outbox/",
 "followers": "https://social.example/alyssa/followers/",
 "following": "https://social.example/alyssa/following/",
 "liked": "https://social.example/alyssa/liked/"}

Ultimately, the choices servers make in constructing the routes they’ll respond to is arbitrary. Maybe the server at kenzoishii.example.com is running a framework that uses that convention to define any route that returns a JSON string. Maybe it is using a file under the hood. Ultimately, all of that is kind of beside the point when thinking about things on the level of HTTP requests—all you know if that you make a POST to the url specified in the inbox property, and it’s up to the other server to handle that correctly.

2 Likes

Then I assume an Actor Object that adheres to the specification and allows for HTTP signatures to work would look something like this:

{
    "@context": [
        "https://www.w3.org/ns/activitystreams",
        "https://w3id.org/security/v1"
    ],  

    "id": "https://tinyrabbit.ml/users/testuser",
    "type": "Person",
    "name": "Test User",
    "preferredUsername": "Test User",
    "summary": "Pretend user to test functionality.",
    "inbox": "https://tinyrabbit.ml/users/testuser/inbox",
    "outbox": "https://tinyrabbit.ml/users/testuser/outbox",
    "followers": "https://tinyrabbit.ml/users/testuser/followers",
    "following": "https://tinyrabbit.ml/users/testuser/following",
    "liked": "https://tinyrabbit.ml/users/testuser/liked",
    "publicKey": {
        "id": "https://tinyrabbit.ml/users/testuser#main-key",
        "owner": "https://tinyrabbit.ml/users/testuser",
        "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu6mKuqaq83M73HUnU+dp\n++g/lG4hAXgElIqlGFe+o4Lp6ISjRVL3BY53N3x+AhFg3UwYWv1VrySNphd1l08X\n43nZ+KeD9qKxDcMLVvFL3LlMJ/QwJ2yeUEPkRrypghQh9n3Vy58l27jLLpxdLz0c\nMs2BFeFheBhXIjy+vVpF28JbHvidxH97vsX28LIgSRKMNDvy/y4l5hmRNvsXkuKa\n4c62lNsVPCiwShb/vcTF+nv1PHeYZhOyH2+kHD3ia+rbwPmqKLTwwYQz/gMMtJnz\nhFtWCI37aKJIH6LmiKSudPZPRvAt+dh4OBPwYYBXgMGNuzdozTAx+YYYMYpT06q2\nQwIDAQAB\n-----END PUBLIC KEY-----"
    }   
}

I’ve merged the Actor Object from the specification with the extra context and public key fields from the blog post I linked to in my original post. Do you think this is a format that most implementations out there would accept?

(The domain tinyrabbit.ml doesn’t exist, and may not ever depending on where I decide to set up a test server for my development efforts :slight_smile: )

Worth noting is that there’s no avatar link in there. Is there a consensus on that out there?

Yep, that looks good to me. preferredUsername is not required by the spec, but it is required by Mastodon and other implementations that use Webfinger as a way of referencing users (examples for this are also in the blog post as well).

You can see https://www.w3.org/TR/activitystreams-vocabulary for more properties of Person, Note, Activity, etc that may not be covered by the ActivityPub spec. In this case, icon is used for the avatar and, if the implementation supports it, image is used for a more free-form image, like a profile header image.

1 Like