Best-practices for AP vocabulary extensions?

I would like opinions on how large “vocab extensions” (this as yet ill-defined concept) should be, so we may find best-practices for it. My take is they should be “as small as possible” to increase their versatility and reuse potential as building blocks (lego bricks) in interoperable solutions.

I tooted about the subject, where I mention the FEP about "Groups federation. This document has an optional part “Groups moderation”.

Now, I don’t want to go into the specific mechanics of Group federation. But say a dilligent developer implements the FEP to the letter to be as compatible as possible. But in their app Groups have moderation as a requirement (i.e. a group must have moderators or it can’t exist). By doing so they are arguably no longer compatible with Groups federation, as they implemented a restricted subset of the broader concept. They implemented “Moderated Groups”.

Which is something very different. In real life I am in many groups and most of them aren’t moderated. Or, if they are, the moderation is different. It is more accurate in those cases to say that the group has a form or governance.

So wouldn’t it be better if there were a Groups vocab extension and a Moderation vocab extension? So that combining these two ‘lego bricks’ allows me to model “Moderated Groups”. Any app that doesn’t support Moderation can still deal with the Group extension in compatible ways.

In my toots I give a further example where I might model “Community with Governance” from vocab extension building blocks.


I feel this discussion is very relevant. For example ForgeFed (ping @fr33domlover) is modeling interoperability between code forges. But forges have a ton of functionality, and arguably the resulting model consist of numerous reusable building blocks. Tasks, Revisions, Labels, Organization structure, etc. There are many ways to slice.

In the FEP about Valueflows support (ping @lynnfoster) there are also many concepts. This includes functionality related to Tasks. Valueflows might be just as foundational a vocabulary as ActivityStreams, providing basic primitives to build on top of, as Lynn suggests.

But we should be wary that the larger the vocabulary the more likely we get incompatible flavours implemented in fediverse apps.

(One might say that ActivityStreams is too large a vocabulary as well. It has very generic “CRUD of Objects” and then things like “Like” that are more relevant to a subset of social apps. Though here this doesn’t pose a problem)

2 Likes

One trend with ActivityPub is using the protocol for its federation features but focusing more on a different purpose than social messaging (altho social messaging might be part of the purpose).

Valueflows is an example of such use, So is https://fab.city/ (which uses Valueflows but then adds a bunch of other stuff for fablabs).

This trend will continue. Some of these federated apps might want to communicate with more social fediverse sites (like social.coop ) but other fedi sites might want to block them.

One way to deal with this trend would be some kind of AP extension that either allows or disallows vocabulary extensions, or other vocabularies, like “allow or disallow Valueflows”.

Valueflows is not the only current vocabulary extension that is in play now, and more will arrive.

VF will tend to arrive in special-purpose software that can also do social messaging. Likewise FabCity, and I suspect likewise other specialized vocabularies or extensions.

Such an extension (to allow or disallow named vocabularies) might eliminate a bunch of problems in one swell foop.(sic).

Also, doesn’t AP already have some provision for ignoring stuff that the current software-in-use does not understand? If not, it should.

@aschrijver This is a really good question. Generally, we want small modular building blocks in our world, right? I do! But Valueflows is an interesting example. It has a relatively simple model due to its origins in the REA ontology, but supports a lot of use cases.

I am thinking of spelling out several example use cases as part of the VF FEP. This will give an opportunity to think more concretely about if/how VF could be modularized and split apart in this context.

Also Domain Driven Design versus ActivityPub - Fedi Fabric - Discuss Social Coding seems applicable.

Yes. A FEP that allows definition of “Compliance Profiles” has been discussed a number of times. Explicitly disallowing extensions is new idea to me. But I imagine compliance profile to mean something like:

This endpoint or actor exposes [these] capabilities and behaviour, as defined in [these] FEP’s.

I’ve drawn a diagram to accompany my thoughts (note: names/terminology are merely examples):

So this is just brainstorm how to slice stuff into more reusable chunks, creating “Lego bricks” as FEP’s and “Lego kits” are the Compliance profiles. An endpoint/actor may support multiple compliance profiles. On top of these profiles apps can add their app-specific “magic sauce”. Core interoperability is guaranteed on the compliance profile level.

I didn’t draw the ActivityStreams vocabulary in the diagram above. It is positioned as some kind of foundational vocab, providing social primitives (the “atoms” of social apps, as it were). Now Valueflows might be just as foundational as we discussed in the toots.

OTOH it may also be more like a Compliance Profile. If I look at the Valueflows ontology model, which is quite intricate, then I’d be inclined to see it like that. There’s be multiple “lego blocks” in that model, multiple FEP’s, if you want to offer it for the broadest possible interoperability.

I don’t know how I would slice VF into building blocks, but I see “Planning”, “Process flow” (or workflows), “Roles”, etc. Blocks that have broader use than Valueflows alone… maybe. Take “Roles” for instance, and this is already part of ForgeFed. Are these concepts incompatible, or should they share the same definition?

Yes, indeed. What is interesting to observe is the distinction between a “business domain” and an “application domain”.

In the diagram above I explicitly did not refer to a concept of “Microblogging”, as it is very arbitrary what that means. It is an application domain. Specific to a type of app.

They are less valuable to achieving broad interoperability when compared to considering business domains. Business domains refer more to actual activity people do to satisfy particular needs. The concepts in these models are generally more app / technology independent.

In the “forge federation” community and to @fr33domlover I mentioned that “federation of code forges” is also indicating an application domain. A code forge is a rather arbitrary bundling of features in an online platform. It is less valuable, and even risky, to analyse models from this perspective.

What you actually want is to federate the real-world processes and activities that are involved with Software Development - the top-level business domain. This domain can be broken down into many sub-domains, still all business domains (e.g. Revision Control, Issue Tracking, Project Management, etc.)

That’s the RDF.type property every object already has. No need to reinvent the wheel.

Could you elaborate? Every URL can be used to dereference a Linked Data object which has a type. But that doesn’t say much of the entire concept model that that actors support, and the heuristics / message exchange patterns that are required to interoperate with the service it offers.

If the Fediverse largely realized how the data structure underneath ActivityPub works, a well-defined ontology would be enough to define all business logic.

An activity is a well-defined transformation on an RDF graph. If we treated it exactly that way, many things would be much easier. Most of the complexity we are facing here comes from implementors notorously ignoring the data structure of the fediverse (because they find tables so much more convenient).

Activities could right now already be described as SPARQL Update operations already instead of just English.

The next step could be defining an ontology for defining transformations, so we could encode the operations necessary to conduct the activity in the ontology itself, which would get us as far as building what “crypto” gangsters call “smart contracts”, all without changing ActivityPub itself.

I think I have order my 3 thoughts on this topic:

  • I like the picture @aschrijver paints with the term “building blocks”. I think this is the dream of everyone writing software to be able to reuse it to do different things.
  • ActivityPub describes a building block called Actor on a Server, which handles asynchronous / federated communication for the Client.
  • Unfortunately, the current ActivityStreams vocabulary does no respect this split into Server and Client part of the communication protocol. For example a Note has a part managed by the client, e.g. content, and parts managed by the server, e.g. id / replies.

New vocabularies and revisited ActivityStreams should take the last point above into account, and split their objects into parts that require the server to do something, and parts that can be handled asynchronously and a completely under the authority of the client.

A good rule to decide where to split might be that it should be possible to encrypt/sign the client part, giving servers no means to open/modify it.

1 Like

Reminds me of the Semantic Web. I lack the knowledge to picture how that works. Do you have pointers to examples how business logic is modeled this way?


I am interested myself in following a method for solution design that starts with non-technical domain analysis and then gradually elaborates this towards implementation into an event-based architecture that is modular and easily extensible.

Just for the sake of example (and because DDG found the image) the domain analysis for an eCommerce app might be elaborated into this diagram and serve as input for implementation:

Event storming model of an eCommerce process

(Note: This diagram is still only very basic, more like the MVP of a eCommerce app. In real-world eCommerce there’ll be numerous edge cases, separate flows, external services invoked, etc.)

What is nice in this approach is that it translates one-to-one to code structures, while it is still non-technical and can be understood by the domain expert.

The orange sticky notes are domain events. If we want to federate parts of this model then the domain events where federation takes place are candidates to be mapped to AP activity types to be transferred over the wire, and yellow sticky notes are entities to be mapped to AP objects. Resulting in formats defined in either a custom AP vocabulary and/or reusing concepts from existing vocabs.

The business logic here is in the implementation of the “aggregate root” entities, the yellow sticky notes. Note that a domain driven design elaborated into a “CRUD of Objects” ActivityPub message exchange on the wire would have similarities to an anemic domain model anti-pattern. Exchange of semantically meaningful activities helps to convey how the domain works and follows ubiquitous language to be universally adopted.

Suppose a requirement is broad interoperability with other federated apps, and strive to offer integration points wherever we find common building blocks. Orders, offers, addresses, inventory, payment, etc. are likely candidates to consider.

This is the development approach where I’d like to find practical ways to map into AP implementations.

just reminded me what should be best practice for any proposal: Provide test cases.

Continuing my point from the previous post: This is especially important if your extensions requires servers to perform side effects. It might be good to state an expectation of what a generic client [1] should display.

[1] I’m well aware that no generic client currently is in wide circulation.

1 Like

Yes! One way to do this technology-independently is to write Gherkin test scripts. They are supported by most markdown parsers to display well in docs, and have out-of-the-box libraries for most language implementation to implement them as behaviour tests. An example where they are used in an ActivityPub context is the did-method-orb spec, where Gherkin features are tested using Golang.

Sure: ActivityPub

Yes, I think I misunderstood your previous comment, and thought you were proposing a universal mechanism for the definition of business logic. I agree that every vocabulary should be accompanied by a well-documented text that describes all the linked data formats, message exchanges, and the conditions on which they take place.

With the FEP’s we are moving in that direction. Docs may be spiced up with ActivityPub sequence diagrams such as @boyter started to create. And FEDERATION.md convention may be improved to have an easy way to find what an app support. I still think Compliance Profiles come in handy as a way to discover the functionality that is available.

:+1:

I agree 100% ActivityPub is Json-LD and Json-LD is RDF. It’s not Json! ActivityPub is also not a subSet of Json-LD.

But a generic RFD implementation is not that easy. i am working on rdf-pub for a very long time :wink:

1 Like

That is currently my solution for an AS:Object, that is posted to rdf-pub.

<http://example.com_7> a <https://schema.org/CreativeWork>, <https://www.w3.org/ns/activitystreams#Object>;
  <https://schema.org/name> "Teikei Gemeinschaft München Trudering";
  <https://schema.org/creativeWorkStatus> "todo";
  <https://www.w3.org/ns/activitystreams#name> "Teikei Gemeinschaft München Trudering";
  <https://www.w3.org/ns/activitystreams#to> <https://www.w3.org/ns/activitystreams#Public>;
  <https://schema.org/description> "Verbrauchsgemeinschaft für solidarischen und gesegelten Kaffee. Hier kannst du ökologisch und sozial anspruchsvollen Kaffee bestellen und dich mit anderen Enthusiast*innen von gutem und nachhaltigen Kaffee austauschen. Bestelle schnell und einfach mit Klick auf unsere Homepage.";
  <https://schema.org/identifier> "9d317daca74246d4be41b1a37e30ee2a";
  <https://schema.org/license> "CC0-1.0";
  <https://schema.org/version> "7"^^<http://www.w3.org/2001/XMLSchema#long>;
  <https://schema.org/about> <http://example.com_7_organisation>;
  <https://schema.org/keywords> "non-profit", "teikei", "teikei-gemeinschaft";
  <https://schema.org/dateCreated> "2022-06-20T15:28:24.362"^^<http://www.w3.org/2001/XMLSchema#dateTime>;
  <https://schema.org/dateModified> "2023-02-04T11:46:39.704368651"^^<http://www.w3.org/2001/XMLSchema#dateTime> .

<http://example.com_7_organisation> a <https://schema.org/Organization>, <https://www.w3.org/ns/activitystreams#Object>;
  <https://schema.org/name> "Teikei Gemeinschaft München Trudering";
  <https://www.w3.org/ns/activitystreams#name> "Teikei Gemeinschaft München Trudering";
  <https://schema.org/contactPoint> <http://example.com_7_contactPoint>;
  <https://schema.org/location> <http://example.com_7_place>;
  <https://schema.org/identifier> "9d317daca74246d4be41b1a37e30ee2a";
  <https://schema.org/version> "7"^^<http://www.w3.org/2001/XMLSchema#long> .

Also thinkable should be:

loa:Organization a rdfs:Class ;
    rdfs:label "SomeObject AP compatible Object" ;
    rdfs:subClassOf schema:Organization;    
    rdfs:subClassOf as:Organization.

am curious about the shit storm :rofl:

No reactions !?
Hope, that’s not because of the turtle. Here the sample in ugly json-ld :wink:

[

   {

      "@id":"http://example.com_7",

      "@type":[

         "https://schema.org/CreativeWork",

         "https://www.w3.org/ns/activitystreams#Object"

      ],

      "https://schema.org/name":[

         {

            "@value":"Teikei Gemeinschaft München Trudering"

         }

      ],

      "https://schema.org/creativeWorkStatus":[

         {

            "@value":"todo"

         }

      ],

      "https://www.w3.org/ns/activitystreams#name":[

         {

            "@value":"Teikei Gemeinschaft München Trudering"

         }

      ],

      "https://www.w3.org/ns/activitystreams#to":[

         {

            "@id":"https://www.w3.org/ns/activitystreams#Public"

         }

      ],

      "https://schema.org/description":[

         {

            "@value":"Verbrauchsgemeinschaft für solidarischen und gesegelten Kaffee. Hier kannst du ökologisch und sozial anspruchsvollen Kaffee bestellen und dich mit anderen Enthusiast*innen von gutem und nachhaltigen Kaffee austauschen. Bestelle schnell und einfach mit Klick auf unsere Homepage."

         }

      ],

      "https://schema.org/identifier":[

         {

            "@value":"9d317daca74246d4be41b1a37e30ee2a"

         }

      ],

      "https://schema.org/license":[

         {

            "@value":"CC0-1.0"

         }

      ],

      "https://schema.org/version":[

         {

            "@value":"7",

            "@type":"http://www.w3.org/2001/XMLSchema#long"

         }

      ],

      "https://schema.org/about":[

         {

            "@id":"http://example.com_7_organisation"

         }

      ],

      "https://schema.org/keywords":[

         {

            "@value":"non-profit"

         },

         {

            "@value":"teikei"

         },

         {

            "@value":"teikei-gemeinschaft"

         }

      ],

      "https://schema.org/dateCreated":[

         {

            "@value":"2022-06-20T15:28:24.362",

            "@type":"http://www.w3.org/2001/XMLSchema#dateTime"

What kind of reaction were you expecting? :thinking: Maybe I didn’t dig deep enough, but that extension style looks reasonable (although the interop would be limited since most AP servers aren’t fully processing JSON-LD or RDF).

Any feedback is welcome :wink:

although the interop would be limited since most AP servers aren’t fully processing JSON-LD or RDF

But can they then called AP server ?

Conclusion, interop and federation is only possible, if you do not use json-ld?

Anyhow, then theres no reason to discuss “vocabulary-extensions” :thinking:

Fredy

I think so. The specification doesn’t require AP implementations to use JSON-LD or RDF. If JSON-LD is used, it does require the JSON-LD to be communicated in a way that it can be consumed as vanilla JSON. In your example, most implementations would ignore (or misinterpret) the parts they don’t understand (like the schema.org stuff). Other servers, like Vocata, would process and fully store in an RDF triplestore. (Of course, much more is required for interoperability than vocabulary or even ontology, but that’s a different discussion.)

It might be interesting to compact your JSON-LD so it is compliant with AP and then post that. It would highlight ambiguous fields like “description” and maybe trigger some discussions about how a plain JSON consumer would (or would not correctly) interpret it.

Maybe I could be convinced, but at this point, I don’t agree. I can understand your conclusion if you view interoperability as absolute (either everything is completely interoperable or nothing is). I don’t view it that way. There are islands of Federverse interoperability. Some of that is interoperable because of AP. Much of it is interoperable because of developer collaboration (explicit or implicit). Many implementations are partially interoperable with either other, but they may be supporting very different social domains (image sharing, value flows, social chess game management versus microblogging, as examples).

I think there are reasons to discuss it. First, it can facilitate the “islands” of interoperable applications in specific domains and assist in making the islands themselves at least partially interoperable. The discussions can also highlight the limitations of plain JSON processing and educate developers about the potential advantages (and challenges) of a linked data approach.

2 Likes