w3c / activitypub

http://w3c.github.io/activitypub/
Other
1.24k stars 78 forks source link

Semantics of embedded `object`s of `Update` activities in collections of activities #408

Open tesaguri opened 10 months ago

tesaguri commented 10 months ago

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.

ap-socialhub commented 7 months ago

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

evanp commented 7 months ago

We have a requirement for the format of Update activities for the following contexts:

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.

trwnh commented 7 months ago

For self-reference later: https://stackoverflow.com/questions/41830542/simple-versioning-in-rdf-data

tesaguri commented 7 months ago

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"
  }
}