FEP-9fde: Mechanism for servers to expose supported operations

Hello!

This is a discussion thread for the proposed FEP-9fde: Mechanism for servers to expose supported operations.
Please use this thread to discuss the proposed FEP and any potential problems
or improvements that can be addressed.

Summary

This document proposes an extension to the NodeInfo schema (FEP-f1d5) that would allow developers of Mastodon and Mastodon-like servers to unambigiously communicate the operations their servers support, and allow developers of software that interoperates with those servers to detect those features, promoting interoperability and easier adoption of new features.

(now with my FEP facilitator hat off)

@nikclayton If this proposal is mostly about the Mastodon API, shouldn’t the operations map be part of it and not NodeInfo? The primary purpose of NodeInfo is exposing server stats, and not all developers are keen to implement it.

The operations map can be added to /api/v2/instance response, that would save a HTTP request. In Lemmyverse developers will probably prefer their own equivalent of Instance API endpoint.

You also mention ActivityPub extensions, but I think any kind of capability negotiation is bad for federation and should be discouraged. Furthermore, extensions are already identified by URIs, reverse FQDN naming is not appropriate for that use case.

1 Like

Hey, sorry for the late reply, I was expecting an e-mail notification of replies, which never came., then someone else pinged me about this. Anyway


If this proposal is mostly about the Mastodon API, shouldn’t the operations map be part of it and not NodeInfo?

The Mastodon API – more accurately, the set of all API methods offered by all past and future versions of Mastodon and similar software (Misskey, Pleroma, Friendica, GoToSocial, etc) – is the motivation for the proposal, because I’m working on a client that needs to implement that.

A previous iteration of the proposal did as you suggested.

But then I realised that the proposal also works – I think – for client/server developers of software that isn’t in the micro-blog niche. For example, Lemmy and Mbin, or Mobilizon.

Developers of those services could adopt this proposal within their own APIs (e.g., Lemmy’s /site API call), but since Nodeinfo is right there, it seemed sensible to use it.

Nodeinfo is also server agnostic; a client can fetch the nodeinfo data without needing to know the server software. This is good for UX, as it means the user does not need to be asked to provide that information, and the client does not need to try different server-specific API endpoints to figure out what it’s talking to.

The primary purpose of NodeInfo is exposing server stats

That’s not obvious from things like http://nodeinfo.diaspora.software/, which says:

NodeInfo is an effort to create a standardized way of exposing metadata about a server running one of the distributed social networks. The two key goals are being able to get better insights into the user base of distributed social networking and the ability to build tools that allow users to choose the best-fitting software and server for their needs.

(emphasis added)

As noted in the proposal, this doesn’t need to be a top-level property in nodeinfo, it could also be a property under the existing metadata property.

that would save a HTTP request

I don’t think that’s a concern, given the volume of requests a client typically needs to make (many of which likely involve hitting a backend database). This is a single, small, highly cacheable request/response.

You also mention ActivityPub extensions, but I think any kind of capability negotiation is bad for federation and should be discouraged. Furthermore, extensions are already identified by URIs, reverse FQDN naming is not appropriate for that use case.

I’m entirely agnostic on the wisdom of ActivityPub extensions as a whole, as someone who works on the client side I’m not really qualified to comment on them further. If they do turn out to be useful this proposal provides a mechanism for them, but that’s very secondary to the main aim of this proposal.

Changing the proposal to use IRIs instead of reverse-FQDN is certainly possible, and might be desirable. The benefits of consistency with other protocols that server developers have to implement might outweigh the case-sensitivity concerns I note in the proposal.

Strong community feedback on that point would be very helpful.

Yes, and by that authors mean tools like https://fediverse.observer. Not everyone wants to provide data to such sites and participate in popularity contests. And while personally I don’t mind providing NodeInfo endpoint, I think it must remain optional, and instance admins should have the ability to disable it.

I think reverse-FQDN is a good idea. That will help separate application-specific APIs and ActivityPub S2S and C2S APIs.

1 Like

Exposing this kind of capabilities to clients is definitely useful for Mastodon and Mastodon clients, not only with other implementations with a compatible client API, but also for Mastodon forks and even Mastodon versions.

I am not convinced this needs to be a FEP or use NodeInfo, though:

  • NodeInfo may imply one domain only runs one ActivityPub server implementation, which is not necessarily true
  • Mastodon clients will typically already fetch /api/v2/instance to get information and server configuration, it makes sense for them to keep doing that and not perform an extra request
  • another thing is software possibly implementing multiple client APIs. In this case, namespacing the operations may become muddy, and clients likely don’t need to know operations across all APIs

Also, one question is how granular the operations should be. Looking at your proposal, a single feature (bookmarks) that is now universal across Mastodon versions, forks and servers implementing Mastodon-compatible API is made up of 4 operations, each identified by a FQDN. This is very verbose, which may be an issue if a client were to frequently request the available feature set.

Finally, there is also some tension between operation versions and other operations: indeed, in your proposal, you mentioned that posting could be seen as having multiple versions, with the addition of the scheduled_at and polls parameters be minor versions. This works, but for instance, glitch-soc has a local_only parameter and a content_type parameter. They can’t be represented as a version, and need to use another operation type, so there is a bit of a conflict there, and I’m afraid any added or changed feature may bring up this kind of discussions.

1 Like

I agree with the second part, but can you elaborate on the premise? Can’t https://server.test/.well-known/nodeinfo provide metadata for one server and https://server.test:8888/.well-known/nodeinfo (or https://v2.server.test/.well-known/nodeinfo) for another server on the same domain?

I understand you qualify the statement with “may imply”, but I’m wondering why it would imply that at all (any more than claiming only one AP server can run at one domain).

server.test and v2.server.test would be two different domains! I meant that nothing forbids https://server.test/foo and https://server.test/bar to be handled by two different pieces of software. Of course, that would be very impractical, and lots of fediverse software already make assumptions based on URLs sharing a domain name, so I’m not sure any such thing exists in practice and maybe guarding against it is a bit silly, but this does sound a bit off to me.

1 Like

Fair enough, but https://server.test/.well-known/nodeinfo and https://server.test:8888/.well-known/nodeinfo would not be.

1 Like

Right, but I was not assuming different ports. This is very unlikely in practice, but there is nothing forbidding multiple pieces of software serving different subpaths on the same domain with the same port. Again, taking that into account may not be worth it considering how unlikely that would be, but still.

It’s a tangent, but although nothing forbids it, the subpaths approach would be problematic since the subpaths could generally overlap in ambiguous ways. For example, is the /a/b/c path in the /an instance or the /a/b instance?

1 Like

Mastodon now has api_versions, but I think it won’t help other implementers:

Something similar to Pleroma’s metadata.features list would be much more useful.

It might help a bit going forward. Currently some clients use the Mastodon server version for determining which API features are available. That means non-Mastodon implementations with their own server version numbers might not interoperate well with those clients. Having a separate API version allows the server and API versions to very independently. :+1:

As far as I know, the current convention is to use the version field:

{mastodon_version} (compatible; {software_name} {software_version})

The new api_versions field provides the same information in a different format. So now clients have to parse two fields instead of one.

I don’t understand. What I’ve seen apps using is the “version” property in the JSON returned from /api/v1/instance or /api/v2/instance. It’s formatted like “4.2.10”.

In any case, it looks to me like Mastodon will start with version “1” for the API version. That’s obviously not the same information as the server version. The server version could change without a change in the API version.

It’s true that if the api_versions.mastodon is not there (in older Mastodon versions), clients will need to implement a fallback to using the server version.

Maybe I misunderstand what you meant by “other implementers”?

I mean other implementers of Mastodon API (Pleroma, some Misskey forks, GoToSocial, Mitra and more), and also client developers that support these platforms. The convention I mentioned is used by some of them.

Yes, clients would not be able to use the User Agent header (if that’s the source of the info you referenced) to determine the API version . I hadn’t encountered those, but I don’t doubt they exist.

Mastodon clients will typically already fetch /api/v2/instance to get information and server configuration, it makes sense for them to keep doing that and not perform an extra request

That doesn’t work for software that isn’t Mastodon clients, or aren’t solely Mastodon clients.

another thing is software possibly implementing multiple client APIs. In this case, namespacing the operations may become muddy, and clients likely don’t need to know operations across all APIs

I don’t understand this concern. The point is that if multiple servers implement the same functionality using an identical API then they expose a single identifier for that operation.

If they implement in mutually incompatible ways then – of course – clients will need to tell them apart.

Also, one question is how granular the operations should be. Looking at your proposal, a single feature (bookmarks) that is now universal across Mastodon versions, forks and servers implementing Mastodon-compatible API is made up of 4 operations, each identified by a FQDN. This is very verbose, which may be an issue if a client were to frequently request the available feature set.

Real-world experience shows that the granularity needs to be lower than a single operation. For example, “search” could be considered a single operation, but in practice clients need to distinguish between the different search operators that are supported to provide a functional UI.

For example:

  • Mastodon 3.5.0 introduced the “from:
” query operator
  • Mastodon 4.2.0 extended the set (“has:media”, “has:poll”, etc), and changed the semantics of “from:
”
  • Mastodon 4.3.0 added a “in:public” query operator
  • GotoSocial only supports “from:
”
  • Friendica supports “from:
” and “lang:
”

See pachli-android/core/network/src/main/kotlin/app/pachli/core/network/Server.kt at 216e3c5b3dfc4959170bde5be8fa7ab7f40b3d82 · pachli/pachli-android · GitHub for details.

Re “this may be very verbose”. Not in any way that matters. Clients only need to request this information when the user launches the app with their account, and any time they switch accounts within the app. The rest of the time it can be cached.

Finally, there is also some tension between operation versions and other operations: indeed, in your proposal, you mentioned that posting could be seen as having multiple versions, with the addition of the scheduled_at and polls parameters be minor versions. This works, but for instance, glitch-soc has a local_only parameter and a content_type parameter.

Yes. Those would all be different operations:

  • Posting a status
  • Posting a scheduled status
  • Posting a status with a poll
  • Posting a local-only status
  • Posting with a specific content-type