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.
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:
(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.
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.
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.
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
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
No reactions !?
Hope, that’s not because of the turtle. Here the sample in ugly json-ld
[
{
"@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? 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
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”
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.
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.
sure ! But in the moment not my priority. I was playing with json-ld framing, but was not able to get an “compatible” , “lightweight” json as other expect. It would be intressting, when anybody that knows that json-ld framing thing define the options to be set to be some kind of interoperable
The other thing is, that if i want to communicate with other instances i’ve to know what types in which format they support. then i can put an adapter in between. See this discussion
Vocata is doing it so you may want to take a look at that. I’ve been able to use Vocata (with a few mods not related to JSON-LD) to interact with Mastodon, for example.
I don’t know the specifics of what you’re trying to do, but it will probably be more complex than someone giving you a list of supported message types and fields (which is not likely anyway in most cases ). The expected behavior and side-effects related to that information (assuming we’re still talking about extensions rather than core AP messages) are also going to be needed (at the very least).
I’m writing a note on this topic for the SocialCG. Here are, I think, the big steps:
- Use a permanent namespace and context URL.
- Create the context document, and write up the standard for discussion in a process like FEP.
- Get “enough” implementers; ideally at least 2 independent implementations.
- (Optional) At this point, people can just add “@context”: [“ActivityStreams 2.0 Terms”, “https://your.example/context/”], and it should just work. But if it’s getting tiresome adding the extra context URL, the SocialCG can approve adding the namespace and terms to the main AS2 context doc, in which case future developers only need to use [“ActivityStreams 2.0 Terms”].
I think the hardest part is making a good design that other people actually use. The rest is just bookkeeping!
That hardest part is the community / social part. Usually when people get to develop an extension for their app they a) want to move quick, get on with coding and b) they are the first / only project with the need for the extension. Taking the time to do the “formalities” and chores doesn’t seem worthwhile, unless it is real low barrier to do so. And then later on, with an established base, the custom extension is harder to generalize as it is used in production. There still isn’t much incentive to collaborate on that as a) “Very busy to keep it all going” and b) “My app works fine”.
I think the very hard part is if you rush through deploying it for your one codebase, and three other implementers take the time to agree on something very different. Now you’re committed to your custom extension that nobody else uses!
Yes, but vocabs were precisely designed to solve that problem. Such that different groups, different projects, different use cases can define their own terms, and the fact that there are different vocabularies enable them to work together, interoperate and resolve naming clashes.
What inadvertently happened in activitypub, and this is partly due to a less than comprehensive understanding, and partly due to long-standing bugs, is that, activity pub diverged from Linked Data in such a way, that the context became a point of centralization. Which is the complete inversion of the design of the thing.
It can be partially mitigated with the extension process. But we need to keep an eye on centralized artifacts, such as “protected” or “sacred” terms, as we saw with alsoKnownAs etc. We need to add controls so that terms dont get rail roaded into the context in a centralized way. But, as long as we are mindful of the risk, it should be fine.