activitypub
activitypub copied to clipboard
Semantics of embedded `object`s of `Update` activities in collections of activities
The ActivityPub Recommendation implies that Update
activities must have a set of the changes (6.3.1) or the whole object (7.3) embedded as its object
property value (at least for client-to-server interactions). But I think it's not quite obvious how this representation is to be interpreted in a collection of activities.
For example, suppose an actor's outbox has the following activities:
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.com/actors/1/outbox",
"type": "OrderedCollection",
"orderedItems": [
{
"id": "https://example.com/activities/2",
"type": "Update",
"object": {
"id": "https://example.com/notes/1",
"type": "Note",
"content": "Hello, world!"
}
},
{
"id": "https://example.com/activities/1",
"type": "Create",
"object": {
"id": "https://example.com/notes/1",
"type": "Note",
"content": "Hello, word!"
}
}
]
}
This might look fine as a plain JSON document, but as an RDF dataset, the embedded object
property values are indistinguishable from each other and the collection would mean something like the following:
@prefix as: <https://www.w3.org/ns/activitystreams#> .
<https://example.com/actors/1/outbox> a as:OrderedCollection ;
as:items (
<https://example.com/notes/1/history/2>
<https://example.com/notes/1/history/1>
) .
<https://example.com/activities/2> a as:Update ;
as:object <https://example.com/notes/1> .
<https://example.com/activities/1> a as:Create ;
as:object <https://example.com/notes/1> .
<https://example.com/notes/1> a as:Note ;
as:content "Hello, world!", "Hello, word!" .
This might not be a problem if the activities are transient and won't show up in the outbox
, but there are desires for collections of Update
activities (among others) like FEP-bad1 (Object history collection).
I don't think the problem can be "fixed" by changing the representation in C2S/S2S interactions since doing so would lead to a compatibility hazard, but I still believe that there needs to be some guidance for publishers who want to have non-transient Update
activities.
I suppose a possible approach would be to clarify that the representation is meant for transient activities only, and that publishers of non-transient Update
activities should use a different representation, without specifying the exact alternative representation just like Activity Vocabulary does in its definition of the Update
activity. Although this wouldn't solve any real-world problem by itself, I think it would at least help publishers make informed decisions.
This issue has been mentioned on SocialHub. There might be relevant details there:
https://socialhub.activitypub.rocks/t/fep-bad1-object-history-collection/3352/7
We have a requirement for the format of Update
activities for the following contexts:
- ActivityPub API: the
object
should be a delta of changed properties, with their new values. - ActivityPub federation protocol: the
object
should be the full set of properties, old and new.
There is no other requirement by ActivityPub on the representation of Update
activities. In particular, it's not possible with the current vocabulary to identify what properties were changed in an Update
activity when you GET the activity with its id
, or if it is part of a collection, like an outbox
.
The representation of Update
activities in the object history collection is up to the FEP process, and isn't generalizable to other contexts.
That said, I'd really like to a have a well-defined property for the "delta" of an Update that can be retrieved in other contexts.
One way to do this is to use the result
property, and have some sort of reified version object, so far undefined:
{
"@context": { "https://www.w3.org/ns/activitystreams",
{ "ver": "https://namespace.example/version" },
{ "dcterms": "https://purl.org/dc/terms/" } },
"type": "Update",
"object": {
"type": "Note",
"id": "https://example.com/user/evan/note/1"
},
"result": {
"type": ["Note", "ver:Version"],
"id": "https://example.com/user/evan/note/1/v/3",
"content": "Hello World!",
"dcterms:isVersionOf": "https://example.com/user/evan/note/1"
}
}
However, this is not covered by core ActivityPub.
For self-reference later: https://stackoverflow.com/questions/41830542/simple-versioning-in-rdf-data
If we could use JSON-LD 1.1 features in the normative context, perhaps we could use "@container": "@graph"
?
Well, it's no use speaking about the past, but if we are to formalize the mecanism with an extension term defined by a FEP, it is probably a viable option.
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"bikeshed": "https://w3id.org/fep/xxxx#bikeshed",
"@container": "@graph"
}
],
"id": "https://example.com/some-file/log/2",
"type": "Update",
"object": "https://example.com/some-file",
"bikeshed": {
"id": "https://example.com/some-file",
"type": "Document",
"href": "https://example.com/storage/hash2"
}
}