Mechanism for representing Account Notes in Actor objects or relationships

Currently some Fediverse software, e.g., Mastodon, allows you to place a textual note on an Account to remind yourself why you follow / block / mute that account.

I’m not sure how best to represent this in ActivityStreams 2 vocabulary, but it would solve an issue with that data missing from our backups which are currently in AS2 json files: Support private note migration · Issue #22709 · mastodon/mastodon · GitHub

We can of course easily enough add these to the CSV file exports, however the zip file based backup we have is AS2 based and I don’t think there’s anything really in AS2 vocabulary for this sort of use case?

2 Likes

I don’t think there’s a good way to do this in AS2, and I don’t think we should limit ourselves to only using AS2 when other vocabularies would work for this.

If I had to represent private notes about an account, I’d consider using something like Web Annotations to represent this:

{
  "@context": "http://www.w3.org/ns/anno.jsonld",
  "id": "https://mastodon.social/users/trwnh/private_account_notes/hachyderm.io/users/thisismissem",
  "type": "Annotation",
  "bodyValue": "working on trust and safety",
  "target": "https://hachyderm.io/users/thisismissem"
}
{
  "@context": "http://www.w3.org/ns/anno.jsonld",
  "id": "https://mastodon.social/users/trwnh/private_account_notes",
  "type": "AnnotationCollection"
}

The only thing missing here for convenience is a way to query a Collection for items matching a certain shape. For example, this is what a SPARQL query that could do it might look like:

PREFIX oa: <http://www.w3.org/ns/oa#>
PERFIX rdf: <https://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?bodyValue
FROM <https://mastodon.social/users/trwnh/private_account_notes>  # this bit is still unspecified, it's not clear how to query collections but this is one way it could be done, if you assume the collection represents a sub-graph.
WHERE
{
  {
    ?anno oa:hasTarget <https://hachyderm.io/users/thisismissem> .
    ?anno oa:bodyValue ?bodyValue .
  }
  UNION
  {
    ?anno oa:hasTarget <https://hachyderm.io/users/thisismissem> .
    ?anno oa:hasBody ?body .
    ?body a oa:TextualBody .
    ?body rdf:value ?bodyValue .
  }
}

Or you could extend the Web Annotations Protocol to accept a basic target query parameter:

GET /users/trwnh/private_account_notes?target=https%3A%2F%2Fhachyderm.io%2Fusers%2Fthisismissem HTTP/1.1
Host: mastodon.social

Sure, there’s the option of defining a “native AS2” serialization of annotations, but why do that when there’s already an existing data model?

The ZIP export would look something like this:

/trwnh
- actor.json
- outbox.json
- ...
- private_account_notes.json

Where private_account_notes.json contains an AnnotationCollection:

{
  "@context": "http://www.w3.org/ns/anno.jsonld",
  "id": "https://mastodon.social/users/trwnh/private_account_notes",
  "type": "AnnotationCollection",
  "items": [
    {
      "id": "https://mastodon.social/users/trwnh/private_account_notes/hachyderm.io/users/thisismissem",
      "type": "Annotation",
      "bodyValue": "working on trust and safety",
      "target": "https://hachyderm.io/users/thisismissem"
    }
  ]
}

This shouldn’t even be that disruptive considering that AnnotationCollection inherits from Collection, and you’re generally going to be processing all the other exported JSON files as Collections anyway. So you can mostly ignore the @context and type, and the only thing you’d need to know to look for is bodyValue and target.

3 Likes

I think this is the first time I’ve actually seen the Web Annotations data model in use, and yeah, that’d work for the zipfile export, I think.

1 Like

Using WebAnnotations for this is an EXCELLENT idea.