This is my suggestion for meta-policy: the structure and policy for processing updates to policy branches. These rules probably have to be set in stone, or at least code, so they have to be right up front, and I don't claim to have gotten 'em right. I think this handles every case outlined in my previous message, though. [Note that I do not attempt to handle permissions enforced at commit or checkout time, nor do I have a plan for pathname-based permissions, only branch-based permissions.]
The basic structure of a policy branch is as Nathaniel proposes it. Policy branches map a name -- we reserve a chunk of the namespace for policy branches -- to a set of key IDs. All branches, content or policy, have an _associated_ policy branch; the set of keys listed in branch X's associated policy branch P(X) is the set of keys that's allowed to present new branch certificates for X. This is checked at netsync time; you can do whatever you please in your local repository, but branch certs that you're not allowed to issue, *and the associated revisions*, are not transferred to other databases. [Naturally, it is the receiving end that has to enforce this, although a polite sender will not transmit revisions that it knows will be thrown away. Perhaps we can wire this into merkle refinement somehow, so that it's impossible for the sender to get it wrong.] A policy branch's associated policy branch gives, naturally enough, the set of keys allowed to modify the policy. It is allowed for a policy branch to name *itself* as its associated policy branch, and in fact there must be at least one such policy branch, to cut off the infinite regression. (I suppose you could also have P(A) = B, P(B) = A if you wanted to be strange.) The branch -> policy relation is declared explicitly in every branch certificate, which means you can change the policy branch associated with a branch X -- but only if you're in the key set for P(P(X)), *not* just P(X). Otherwise the cert must declare the same policy branch as its parent revision's branch cert. (For merges, it only has to agree with the parent with the same name.) When you create a new branch from a given revision, the policy for that branch is normally the policy of the parent rev's branch. However, if the parent rev's policy doesn't include your key, you have to specify a policy that does include your key (either on the command line, or in lua hooks, to save typing). At that point the *other* thing in each policy branch kicks in: a restriction of some sort (a list of globs, perhaps?) on the branch names that are allowed to be generated using that policy. These two things together give us a full-fledged branch-based permissions mechanism. Now, we also need rules for dealing with conflicting updates to a given policy branch. I propose a very simple rule: Netsync refuses to create divergence in a policy branch, except if being run in "sink_role" (i.e. "pull"). And if it is run as "pull", and divergence is generated, you are *immediately* required to merge heads. This will never inconvenience a user who doesn't touch policy branches, unless they try to pull from two databases with conflicting policy branches with the same name (i.e. both sides of a totally hostile fork) -- anyone doing that can probaly be assumed to know what they are doing. It may be a minor inconvenience for admins -- suppose Alice adds Carol to the main policy branch, and Bob adds Dave at the same time; one of them will get their sync rejected and have to pull, merge, push. However, this would be a concern no matter what. So you can't diverge a given policy branch; but you can create all the new named policy branches you want, either from scratch or by branching existing policy branches, and have them say whatever you want. However, you cannot override the existing policy branch for any existing content branches (or more precisely, you can, but netsync will refuse to push them into any database where you're not allowed to do that) -- so you are forced to create your own content branches at the same time. This ensures that a user tracking the primary dev branch for one side of the fork can just carry on. What happens if you take yourself out of the set in a policy branch? Well, first, note that this is only a concern for a policy branch whose policy branch is itself. Second, once the revision and its branch cert are accepted by netsync, they stay accepted. Third, the decision to accept the revision is made by the recipient - who doesn't have that revision yet, so they base their decision on the *previous* policy, which said you were allowed. Thus, the oscillating cspec scenario is not possible. If Mallory and Nogoodnik kick each other out of the policy branches, whoever does it first wins (this follows from the above rules). I claim that we cannot, programmatically, do any better than that. If the consensus of the team is that whoever came second was wrong, well, hopefully there is also Trent still in the master policy branch to sort it out. Or at least, someone who can shell into the netsync server and replace the database by hand. If Mallory overrides every last policy branch in the database with "Mallory and nobody else", and Mallory also happens to be the sysadmin for the machine hosting the netsync server, well, the project is just going to have to get a new hosting provider. However, note that the Absolute Write disaster scenario (malicious ISP refuses to give site owners a database dump so they can set up elsewhere) cannot arise, as everyone already has a complete copy of the database on their local disk; the devteam- in-exile can just take one of those, promote it to netsync master, and go on. z "Thoughts?" w _______________________________________________ Monotone-devel mailing list [email protected] http://lists.nongnu.org/mailman/listinfo/monotone-devel
