'describes' property of 'Profile' object: why is this specified as Object only, and not URI or Link?

Hi all

In working on my validator for ActivityPub data, I’ve come across something in the ActivityStreams spec which looks to me (unless I’m misunderstanding something basic) to be a mistake.

The describes property of the Profile object is described as

Domain: Profile
Range: Object

This is unusual: I would expect the range to be Link | Object. The reasons I would expect this are

  1. Most properties which take Object values also take Link values;
  2. Any Profile certainly describes an Actor, and the Actor object must also exist in the system with its own URI;
  3. Copying the data from the Actor object into the Profile object creates duplication; it is at best redundent and at worst risks inconsistency.

Am I right in thinking this is an error in the spec and that in the real world, a URI value for the describes property should be accepted? Or should I enforce the rule that this should be an explicit local Object?

1 Like

when you refer to an Object by its id or IRI, that is not a Link, but rather part of how linked data works.


While I’m on this, the formerType property of a Tombstone object is specified to be an Object. Again, surely that should be an anyURI? Essentially, it’s going to be a string (or list of strings), isn’t it?

yes, that one seems like a mistake. The range of formerType should match the range of type, that seems straightforward.

For your question about Profile, I think you misunderstand the different between an URI and a Link. A Link is a new qualified reference object. For example, here is an example of a link given in the spec:

  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Link",
  "href": "http://example.org/abc",
  "hreflang": "en",
  "mediaType": "text/html",
  "name": "An example link"

Consider the example given in the spec (Example 141), where we have a Profile that describes an actor Sally. This is what that example would look like if describes took a Link range:

  "@context": "https://www.w3.org/ns/activitystreams",
  "summary": "Sally's profile",
  "type": "Profile",
  "describes": {
    "type": "Link",
    "href": "http://example.org/Sally",
    "hreflang": "en",
    "mediaType": "application/activity+json",
    "name": "Sally"
  "url": "http://sally.example.org"

alternatively, this is what it can look like today, when describes takes an Object range:

  "@context": "https://www.w3.org/ns/activitystreams",
  "summary": "Sally's profile",
  "type": "Profile",
  "describes": "http://example.org/Sally",
  "url": "http://sally.example.org"

See the difference? In the Link example, we’re pointing to a new anonymous object that has the href property, which allows us to also add other properties, like mediaType and hreflang to the Link object. But in the Object example, we just reference the Actor object directly, and there’s no new intermediate Link.

Does that clear things up?

Yes, thanks. My validator is now sort-or working, but for hackers only. I’ll do a wrapper round it which makes it usable to other people shortly. It’s currently picking up 253 faults in the test documents suite (205 documents), as follows:

dog-and-duck.scratch.core=> (pprint (distribution :severity r))
{:should 204, :must 47, nil 2}
dog-and-duck.scratch.core=> (pprint (distribution :fault r))
{nil 2,
 :paged-collection-invalid-first 1,
 :invalid-to 1,
 :invalid-name 2,
 :invalid-target 1,
 :invalid-next-page 1,
 :paged-collection-invalid-current 1,
 :invalid-icon 1,
 :invalid-actor 1,
 :invalid-url-property 2,
 :invalid-prior-page 1,
 :invalid-attribution 2,
 :invalid-attachment 1,
 :invalid-longitude 1,
 :invalid-tag 2,
 :paged-collection-invalid-last 1,
 :invalid-type 4,
 :no-actor 6,
 :invalid-audience 2,
 :invalid-image 4,
 :no-context 204,
 :invalid-direct-object 1,
 :invalid-latitude 1,
 :missing-part-of 5,
 :invalid-option 5}

Some of these are undoubtedly down to my misreading of the spec, but I think this is now shaping up to become a useful tool.

1 Like