This is a topic for community work on FEP-3447: Endorsements. The early-early-pre-draft is currently on my own GitHub, but should be moving to the official Codeberg repository soon.
I recently started a discussion on Mastodon that is ready to move to a bigger venue. So here we are 🤓
Yes, exactly. It’s not AP now, so it’s not technically reusing the name. If anything, we’re taunting Mastodon to just connect up what they’ve already got in place. Though, they may be ditching this in favor of their new “Collections” feature – which will be very cool.
@benpate I still agree with @[email protected] that Endorsement makes more sense because it’s metadata can be updated (content, tags, etc.)
Like, block, etc. don’t have that additional concern AFAIK. However it’s not a sticking point for me and I am ok with whatever.
Ok. I’m going to rewrite it as a noun and see how that works.
@[email protected] - how would these semantics be different from the definitions we already have in Activity Vocabulary? And, if the existing
AcceptandRejectactivities aren’t meant for this, what are they meant for?@julian - Since I’m the next guy, we’ll have to arm wrestle over who’s more against JSON-LD :)
@[email protected] @[email protected] @[email protected] The point @[email protected] is trying to make is that side-effects differ based on the Object an Activity points to. So if you are ingesting an Activity of type Accept, you have to dereference the Object, fetch it or look it up in the DB, check the type of the Object and then decide what to do.
With pseudo-namespaces, you see an Activity type that is unique to an Object type. There is no special handling for each type as it doesn’t matter. Depending on how painful implementing new AP types is in your software, using namespaces is cleaner and more obvious. If it’s a pain to implement new types in your software,…
@[email protected] This implementation detail is a good point. Thank you for clarifying.
In my own software, I think we’re already doing this - dereferencing the “object” of an activity before I route it to the appropriate transaction handler. Given all of the different kinds of activities we have to accept, it seems like this would already be a requirement for any ActivityPub server, yes?
@[email protected] considering the Endorse (or Endorsement) object needs to be resolved anyways as it contains potentially relevant metadata, it seems the “save network requests” argument is moot.
It’s not especially hard to add new activity handlers in NodeBB, it’s just a personal preference.
@julian I’m spinning back and forth on this. Should this be a noun or a verb? In a way, it’s kind of irrelevant - we could query this data all the same whether they’re objects or activities.
Pros for Activity:
Follow,Like, andBlockare all activities.Endorseshould feel parallel to them- We have other examples of actors
Accept-ing andReject-ing other activities. - Mastodon API already publishes
Endorsement, so we shouldn’t overlap with that.
Pros for Object:
Offer(Endorsement)reads cleaner thanOffer(Endorse)- As a noun, an
Endorsementfeels like something I could pick up and hold, attach a signature to, or put on my home page. - Mastodon API already publishes
Endorsement, so we’d just be opening this up to a broader ActivityPub audience.
Do you mean this API endpoint?
https://docs.joinmastodon.org/methods/endorsements/
It’s not AP, so it’s not conflicting with this FEP, no?
TIL Mastodon has endorsements.
@benpate @technical-discussion
>Given all of the different kinds of activities we have to accept, it seems like this would already be a requirement for any ActivityPub server, yes?More or less yes, but that doesn’t mean it must be that way forever. Currently Accept/Reject is mostly only for follows for example. Now if I add something like group chat Invites, the two would have completely different side-effects.
I don’t really have a preference for one over the other, as the language I would use solves the type check for me via pattern matching. But if it wouldn’t, the result would probably include a giant switch/case statement somewhere in the object logic and a plethora of handle_incoming_type_asdf functions for each Activity(Object) variation supported.
The network request point is kinda moot, as you would want to derefence (and fetch) the Object most of the times anyway. At least for me it’s about developer experience (clarity), getting rid of JSON-LD while still getting some validation and removing possible semantics conflicts between FEPs and/or different extensions. The last is solved by LD, but I want to get rid of it instead. As a bonus, instances not supporting the extensions will drop it early instead of making requests only to drop the Activity in the end.
Yes, that’s a good idea. I’m hoping we can make a really streamlined document for the protocol and then to put the other important “how to use this” stuff into some separate document. So it makes sense to put context types somewhere else, too.
For the very short term there’s a lot of overlapping conversations so it’s easier for me to dump everything into one big messy document. Will that work, with the general understanding that context URIs break out into their own FEP long before we start building?
Thanks for this. All good points :)
Add “FEP-8b32 Object Identity Proofs” into the mix, and we may get to skip one of those HTTP lookups. We’re going to NEED signatures on endorsements to keep people honest, with the side-benefit of simplifying some network stuff in the meantime.
Can
contenthave some prescribed shape or specific attestations? Or maybe better asked, would I be able to say “I trust Bob for matters pertaining to cooking and carpentry, but not windsurfing” ?As it stands now,
Accept,RejectandUndoare identical to activities related to a follow relationship.I suggest picking more descriptive names for activities:
-
OfferEndorsement
-AcceptEndorsement
-RejectEndorsement
-UndoEndorsementAnd maybe
Endorseshould be an object instead of activity? An endorser may want to update the endorsement metadata (content, image, tags).Hey @[email protected] !
I tried to use the existing vocabulary as much as possible. It seems like this fits the existing grammar, does it not?
{ type:"Offer" object: { type:"Endorse" } }Also, Gilles makes a strong point to just use the word “Trust” – it’s simpler and better known around the world. What do you think of that, instead?
Also, Gilles makes a strong point to just use the word “Trust” – it’s simpler and better known around the world. What do you think of that, instead?
I prefer “endorse”. IMO “trust” is too vague and often used in discussions related to security.
In the user interface, the different flavors of “endorse” could be described using other words.I don’t know. Why do you want to use the existing vocabulary?
A descriptive activity name leads to a better developer experience:
- You can look at activity and instantly know what action is being performed.
- Servers that implement your FEP don’t need to use heuristics, look upobject, etc. to figure out what’s going on.
- Servers that don’t implement your FEP silently ignore unsupported activities, without wasting any resources.@[email protected] @[email protected] @[email protected] If you are going through the trouble of using your own vocabulary, why not at least make it so that namespace conflicts don’t ever happen again, similarly like they do with semantics using AS Vocab now.
If you implement
OfferEndorsementand I want to use it as well, but for something incompatible with your thing. Then I guess I need to invent a new less descriptive name for my thing like:NewAPServerOfferEndorsement, if you effectively reserve that name for your thing and depend on that name being unique for handling.So I think, something like below is a better solution to the same problem, while admittedly looking worse:
fep-3447:OfferEndorsementfep-3447:AcceptEndorsementfep-3447:RejectEndorsementfep-3447:UndoEndorsement
Or
fep-3447:Offerfep-3447:Acceptfep-3447:Rejectfep-3447:Undo
@phnt I wouldn’t say that introducing a new vocabulary is a trouble (unless you care about JSON-LD, which requires deploying a website every time you invent a property or type)…
But you’re right, it’s better to use prefixes - I already started doing it in my FEPs. Prefixes could be dropped once a FEP is finalized.
@[email protected] @[email protected] look, I’m against JSON-LD as much as the next guy, but isn’t that the whole point of JSON-LD — so you don’t have to do these contrived naming shenanigans‽
@[email protected] @[email protected] @[email protected] The point is getting rid of JSON-LD while still getting pseudo-namespaces.
If you wanna use JSON-LD to verify those semantics, you are free to do so, but that is entirely optional.
@[email protected] yeah but I’m also saying you don’t need JSON-LD to adequately distinguish between embedded objects. People have been doing it for decades already. No pseudo-namespaces, no JSON-LD
We’re already derailing from the main topic at hand :stuck_out_tongue_winking_eye: perhaps we can both agree JSON-LD is pointless and move on.
> As it stands now, Accept, Reject and Undo are identical to activities related to a follow relationship.
I disagree, I think using existing vocabulary is superior. You probably already distinguish your logic paths based on the object.
In fact, that this FEP uses a scheme similar to existing Follow relationships makes it easier to adopt.
Ben, I’d even put in a blurb to make note of the similarities, and how they’re intentional.
> @[email protected] said: > > And maybe Endorse should be an object instead of activity? An endorser may want to update the endorsement metadata (content, image, tags).
I agree with this.
Offer(Endorsement)sounds better.@julian Yeah, the Noun/Object form may be cleaner than Verb/Activity. I don’t have a good reason why I chose one over the other. It’ll probably change the FEP name and number, but that’s not really a big deal.
This also aligns better with Mastodon’s existing “Endorsement” objects
I’ve updated the document to use “Endorsement” as an object (instead of “Endorse” as an activity). This changes the name to “FEP-d471: Endorsements”. I’ve also tried to incorporate a number of the ideas and suggestions here, including a
contextURI to identify specific KINDS of endorsements, as well as explanations for many common questions.If you’re following this, now is a great time to revisit the FEP. This whole thing will be migrated to Codeberg soon (a PR is already in the works) and this will be the primary place to discuss updates :)
@benpate could Endorsement types be split off into a separate FEP? I think keeping things simple makes it easier for potential devs to digest.
Endorsements MUST have a context property, which contains a context URI that identifies the nature of the endorsement.
This usage conflicts with FEP-7888. If you’re modeling
EndorsementafterRelationship, perhapsrelationshipproperty would be more appropriate?Endorsements MUST have a proof property, which contains an Object Integrity Proof as defined in FEP-8b32. This is required to prevent someone from changing an endorsement maliciously after it has already been accepted.
Who generates this proof? Who owns the
Endorsementobject?This information is crucial for the verification of proofs, see https://codeberg.org/fediverse/fep/src/branch/main/fep/8b32/fep-8b32.md#proof-verification.
Server admins MAY make server-level endorsements on behalf of the server’s Application actor.
This statement links to FEP-2677, which requires discovery through NodeInfo endpoint. Consider using FEP-d556, which recommends Webfinger instead.
Yes, an
Endorsementis very similar toRelationshipand I wrestled with this a bunch. But I think we’re modeling a one-way relationship, not two way. I think it’s something like this:Relationship: Alice <- work together -> Bob Endorsement: Alice -> endorses work product -> Bob
And in more practical (and less theoretical) terms, this new object allows us to assume tighter controls around how an
Endorsementwas made. As under-specified as it is, I could post a validRelationshipbetween myself and Robert Plant (I did meet him once) and there’s no way to verify it. Using a new object, likeEndorsement, we can rely on the workflow around this object a little more, and can verify that Robert Plant actually acknowledged my endorsement (but I’m certain he wouldn’t remember me, the kid in the bookstore)So, we should reuse as much of the existing vocabulary as we can (
context,content, etc) but I think there’s a good reason for a new top-level object.Two thoughts:
-
7888 doesn’t lay claim to
context, additional uses are encouraged, even -
Suggest downgrading requirement of proof to MAY. Upgrade it to MUST in a new FEP. Some of us have no immediate plans to support object integrity proofs. Especially since an endorsement is resolvable, there’s no need for a proof — t’is merely a convenience.
-
I’d rather not use Object Integrity Proofs either, and I’d be happy to cut them entirely. But here’s the big issue I’m concerned about:
Someone may endorse me for one thing (Ben likes Tea) that I’m perfectly ok with. I accept the endorsement, but then they maliciously change the endorsement (Ben likes Coffee, gross) and I still keep their endorsement, leading me to lots of embarrassment.
Is there another way around this issue that DOESN’T require Object Integrity Proofs?
@benpate thinking out loud, we don’t need proofs to do this, they just guarantee that the object the proof is attached to hasn’t been modified in transit.
What you need is a checksum! sha256 hash with each Endorsement object. Maybe that hash forms part of the id itself, then you don’t need a property.
Not sure who’s going to yell at me for that one.
contentshould probably be free-form HTML, so maybe not? But we definitely need something – I’m kicking around eithertagorcontextfor this.I’m leaning towards
contextbecause we could define URL-like namespaces for specific things, where tags are usually more of a “folks-onomy” and therefore harder to aggregate.What do you think?




