This is a WIP document.
It's related to the user story of Build your Web of Trust and Communities.
Problem
In our current implementation users cannot revoke the Capabilities they delegate. Not being able to kick people out is not an option for any reasonable community.
In any auth system, especially those that aim to be peer-to-peer, revoking permissions is always the hardest part. Mainly because of the eventually consistent nature of P2P systems — enforcing authorization without having a consistent view of the world means that sometimes we need to be able to undo things that we might have accepted previously. Aside from posing a programming challenge, there's a lot of user-facing UX concerns that need to be addressed as well.
Solution
Not everything needs to be authorized
Not all blob types we have require authorization. In fact, only a few of them do.
Change — doesn't need authorization. Changes are "brought into reality" when Refs point at them.
Ref — require authorization. For a Ref to be valid there needs to be a Capability granting the permission, or Ref must be signed by the owner of the Space.
Comment — doesn't need authorization. Anybody can create comments. Based on who wrote them, comments could be included into the "official" view of the site, but we don't have that implemented yet.
Contact — doesn't need authorization currently. Owner keys issue contacts in their own account. At some point AGENT keys should also be able to issue contacts for their parent account.
Capability — currently doesn't need authorization, because we don't have ADMIN role yet — only owners can invite people into their space. At some point this needs to be implemented.
Profile — requires authorization when an AGENT key updates the profile of its parent account. This is currently implemented.
Capabilities vs. ACL
Even though we based our authorization system on the idea of capability-based security, the actual mechanics of our system also have some properties of an ACL. In fact, I'd say it's a spectrum, and we lie probably somewhere around the middle.
An important part of our system is that we have a strict "chain of command" set of roles that we assign to users, where there's always someone with more authority — either an admin or directly the owner of the key. This makes it easier to resolve any potential conflicts and disputes, but relies on the premise that the owner's key is safe, and has the final say in everything.
In a more pure capability-based system, delegations and attenuations are typically not restricted — as long as you have a capability you can delegate it further, with the same power or lower (never greater of course). But as much as I like this idea, I don't find it very useful in real life — people are used to strictly control access to their things, and if they wanted you to be able to invite other people, they would give you a permission powerful enough for doing that. And if they didn't — then they don't want you to invite other people. When someone gives you a key for their car, they usually expect you not to copy that key to give it to somebody else.
So, our system doesn't support straight delegations of capabilities. E.g. if you are writer you can't invite other people by delegating your capability further, because writers can't invite people. At least this how it's coded for now. We'll designate an admin role or something like this to allow people invite other people.
Rabbit Holes
Healing recursive delegations when revoking. E.g. in Alice -> Bob -> Carol when Alice revokes Bob she needs to issue a Capability to Carol to heal the authority chain. Otherwise Carol gets revoked too (which may be the desired outcome).
A broader (more powerful) capability may supersede a more narrow one. We might want to garbage-collect those. We also need to define a total order of Capabilities.
AGENT is the most powerful capability, and can have no caveats.
ADMIN (we don't have it yet) is almost like AGENT, but without the "impersonation" part.
WRITER can have caveats (space + path). Shorter path prefix is more powerful, so it could supersede longer paths with the same prefix.
Revocation of delegations vs. negating the caps.
Should revocation specify exact Capability it revokes, or should it express a negating effect of the delegation? E.g. instead of saying "I revoke the Capability with this hash" it could say "I remove role X for key K, so there's any capability claiming those — ignore it".
We need to be able to "unindex" already indexed blobs.
Private documents.