Description
Hello,
I am working with the ForgeFed working group on federating software development platforms (already mention in #1612 and #184).
While the spec is still in the works, I think some basics, independent of the actual content and requirements of the spec can already be implemented to prepare for federation.
Building on this preparations it might be easier to build a Gitea-ForgeFed PoC to better understand the things the spec needs to cover.
Or you could even implement an Gitea-specific federation, although I guess that might be unfair to ForgeFed :P
To me one of this basics is addressing the challenge in the difference of assumptions centralized and decentralized systems make about users.
Federation is a decentralised system made up of centralized systems, so this differences will need to be addressed if you want to support federation.
One (to me central) difference in assumptions can be expressed through the question
of the interchangeability of the "user" concept of centralized systems and decentralized systems.
For example in both centralized and decentralized systems as PR object will be attributed to something that can be conceptualized as a user.
In a centralized system that user can be uniquely identified and addressed just by the username.
While usernames are still a thing in federated systems, there they are neither unique nor are they enough to identity the user, you need additional information for that. In federated systems this information normally is the instance. Together they then form the federated ID.
(Please excuse the cryptic nature of the following paragraph, but for completeness I want mention it here anyway:) While for the UI level user and instance would enough, on the technical level it's not enough for ForgeFed. Due to building on ActivityPub, in turn leveraging Linked Data concepts, which in turn build on the Web, internet-level username+instance is not enough and you won't get around URIs on the Web-level. Due to it and it's limitations already mentioned in the linked issues, I leave off WebFinger here.
Anyway, this issue is concerned with the change of the central identifier of user's from their username to an federated ID (in whatever form).
There are this strategies I am aware of to add a federated ID to an data model (there are not completely nor genuinely mine):
- add the federated ID to the user entity
- use an dedicated entity for users coming from federation
- split the user entity into "Authentication" and "Identity" entities, where local users have both and federated users just the latter.
I, personally, am in favour of the third option because to me that is the clearer way to address the changes that are required to the object model.
If you just add the federated ID to the user entity this means you also have to break a central assumption about the user entity: their usernames no longer being unique. I feel uncomfortable with the implications this leads to, mainly concerning the mix-up of the local-authentication and general-identity domains.
You could also introduce federated users as new concept with their own entity.
This also means you will have to touch all the areas that are concerned about displaying or attributing users. I think you won't get around that if you want to do it good and right. But additionally you will have to duplicate things that you already have for users, like profiles, maybe display logic, etc. (Go not having generics even making this harder to implement and maintain non-redundantly.)
This brings me to the third approach, separating the user entity.
It builds on the assumption that the user entity actually is made up of two entities, the authentication (for login) entity and the identity entity.
The two entities are not independent in centralized systems, so they are combined into one. In federated systems on the other hand they are independent: Not every identity has login information associated with it. Due to that it does not make sense to combine them. This leads to the proposal of splitting up the user entity.
You then have one entity with (login-)username, password and the corresponding identity reference. And one entity with all the other identity suff, like the display name, (non-unique) username, federated ID, avatar URL, ...
While you still need to touch much code, in this case you than can use the identity entity for both local and federated identities, sharing the logic surrounding them (e.g. profiles) :)
So far my stance on this. While I am in favour of my approach feel free to advocate for the other approaches, in the end it's mainly a point of view, I am open to input. :)
Thanks for reading.