Governance: unlisted by default, published by explicit rule #68
Loading…
Reference in a new issue
No description provided.
Delete branch "worktree-agent-ace0a9a921526a954"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements the exposure model from the revised spec section: a governed repository is unlisted and unreadable without authentication unless a rule says otherwise.
@anonymousis a reserved principal in the rule table — an access decision, resolved by the same first-match-wins evaluation,-included. It is kept out of@allby a short-circuit inuser_matches: an anonymous subject matches the literal@anonymoustoken and nothing else, and a named principal never matches@anonymous.listedis anoption, gitolite's syntax, evaluated separately and gated on the read grant.Config errors, both rejected at push validation with a line number:
option listed = yeswithoutR = @anonymousin force. Checked by evaluation over the whole file, so the grant may live in another block; a wild pattern names nothing enumerable, so the evaluator gatesis_listedon the same grant and fails closed there.@anonymousin any permission other thanRor-.The inverted default belongs to the governed world: with no
settings.git,server.tomlstill decides and everything is listed and served as before. Where governance is in force,access.confnow supersedesserver.tomlon the anonymous axis too, in both directions — a privateserver.tomlcannot subtract what a rule grants, and the most permissive one cannot publish what no rule grants.The
apply_governance_default/without_anonymous_accessspecial case is removed: nothing grants@anonymousanything until an operator writes a rule, sosettings.gitis off the anonymous surface by the default rather than by its name. One behaviour change falls out — an unpopulatedsettings.git(noconf/access.conf, governing nothing) is now an ordinary repository on an ungoverned server.Tests: end-to-end over real HTTP against live servers for all three exposure states, the ungoverned regression, both config errors (rejection plus the previously-live config still governing), wild repos, and
agents/settingsnot being mistaken for the governance repository; release downloads following the grant; unit tests for the rule language and forExposure. Full suite green,cargo clippy --all-targetssilent.Migrated from git-collab patche
1beeb03e3f61a0e5b7ab6b154b1554e30eb492d5.Original author: a73x dev@a73x.sh.
Fixes #65
Revision 1:
805398875c783cf26bcd7eb90b25806b637dd3b9; base132d9eca87075cc36055e5e7f3c4219dd0339b35Revision 2:
18181599bcad7189f68712568637795d0e5a6436; base132d9eca87075cc36055e5e7f3c4219dd0339b35Close the unpopulated-
settings.gitwindow at the source.A push to
settingswhose resulting tree holdskeydir/withoutconf/access.confis refused — by the resulting tree rather than the diff, so pushing the roster first and deleting the rules later are the same rejection with the same message. The message names the fix, because an operator hitting this is mid-bootstrap: push both together, orconf/access.conffirst.Rule 3 holds at the boundary: no
settings.gitat all, and asettings.gitwith neither file, both stay ungoverned and behave exactly as before. Only a roster without rules is refused.A repository already in that state is on disk where no hook can reach it, so
governance::unruled_rosterreports it once at startup and does nothing else. Hiding it would reinstate the second mechanism the closed-by-default posture exists to avoid, and refusing to start would take down a server over a repository it has been serving all along.Tests: pushing
keydir/alone is refused, the message names both halves and the fix, and nothing lands (settings.git's HEAD does not resolve); pushing both together is accepted, and from that moment the server is governed and the roster is closed by the default; deleting the rules while keeping the roster hits the same check, asserted on the message so it pins which check fired; a settings repo with neither file still takes an ordinary push. Unit tests cover the tree check's four cases and the startup detector. Full suite green,cargo clippy --all-targetssilent.