Documentation
Git access control and grants
Everlock uses a path-based grant system to control who can read from and push to repositories. Every access decision — clone, push, admin action — is checked against a table of grants attached to users and groups. This page explains the model, the commands, and common patterns for sharing repositories across a team.
The three roles
Every grant assigns one of three roles:
| Role | Can clone (read) | Can push (write) | Can delete |
|---|---|---|---|
reader | Yes | No | No |
writer | Yes | Yes | No |
owner | Yes | Yes | Yes |
Roles are ordered: owner implies writer, writer implies reader. Assigning owner to a user gives them all three capabilities.
When you create a repository with /git create, you automatically become its owner.
When /site create creates a site, it automatically grants the creating user writer access to the underlying store.
The access path format
Every grant is scoped to an access path with exactly three segments:
frontend / backend / namespace
| Segment | Meaning | Example values |
|---|---|---|
frontend | The protocol the request arrives on | ssh, http, * |
backend | The backend family | git, site, * |
namespace | The specific resource | my-repo, * |
Any segment can be * to match all values of that segment:
ssh/git/my-repo — my-repo over SSH only
*/git/my-repo — my-repo over any frontend
ssh/git/* — all repos over SSH
*/*/* — everything (system owner)
Which path to use when granting repository access
For Git repositories, */git/<name> is the right pattern in almost all cases. It covers both transports at once — ssh/git/<name> and http/git/<name> — so you do not have to update grants when a repository becomes reachable a new way:
/users grant alice */git/my-project writer
Use ssh/git/<name> only when you deliberately want to restrict access to a specific frontend and deny it on others.
Granting access to a user
/users grant <login> <path> <role>
Examples:
/users grant alice */git/my-project reader
/users grant bob */git/my-project writer
/users grant carol */git/my-project owner
Grants take effect immediately — no restart required. The user can clone or push as soon as the grant is recorded.
Contribution grants: propose without pushing branches
The namespace segment supports a container:member form for git: <repo>:pulls names the refs/pull/* namespace within a repository. writer on it allows opening, updating, and closing pull requests without any access to refs/heads/* or refs/tags/* — the most common collaboration shape, may propose changes but may not touch branches.
A contributor is the two-grant pairing:
/users grant carol */git/my-project reader # clone, fetch, review
/users grant carol */git/my-project:pulls writer # open + update PRs
Two rules keep this predictable:
- A container grant covers the member. Every existing repo
writer/owneralready covers:pulls— no extra grant needed for full-access users. - A member grant never covers the container.
writeron<repo>:pullsimplies nothing on the repo itself, not evenreader— hence the pairing above.
What each grant set can do:
| Operation | reader | reader + :pulls writer | writer | owner |
|---|---|---|---|---|
| clone / fetch (incl. PR refs) | ✓ | ✓ | ✓ | ✓ |
push refs/heads/*, refs/tags/* | ✗ | ✗ | ✓ | ✓ |
| open / update / close a PR | ✗ | ✓ | ✓ | ✓ |
/git pr list | ✓ | ✓ | ✓ | ✓ |
/git pr open / close | ✗ | ✓ | ✓ | ✓ |
/git pr merge | ✗ | ✗ | ✓ | ✓ |
| `/git repo set | unset` (history retention), delete | ✗ | ✗ | ✗ |
Merging stays with branch writers because a merge writes refs/heads/<target>. In a mixed push, each ref update is authorized on its own: the PR refs apply and the branch refs are answered with ng <ref> access denied.
Everyone holding :pulls on a repo shares stewardship of its refs/pull/ namespace — PR refs carry no per-creator ownership. For strict isolation between proposers, grant :pulls per user rather than to a broad group.
Granting access to all repositories
To give a user access to every repository (for example, a CI account that needs to clone everything):
/users grant ci-bot ssh/git/* reader
This grants ci-bot read access to every repository over SSH. Combined with a writer grant on a specific repo:
/users grant ci-bot */git/deploy-config writer
The user picks up the highest matching role for any given path.
Revoking access
/users revoke <login> <path>
Example:
/users revoke alice */git/my-project
This removes the specific grant. If the user has other grants that still match the path (for example via a group), those remain in effect.
Inspecting a user's grants
/users grants alice
Expected output shape:
alice
grant: */git/my-project writer
grant: */git/config reader
This shows every explicit grant on the user, useful for auditing before adding or removing access.
Groups
Groups let you grant access to multiple users at once. Any user in the group inherits the group's grants. This is the right model for teams — grant the group, then add and remove members without touching individual grants.
Creating a group and adding members
/groups create <name>
/groups assign <group> <login>
The Groups page walks through the full team setup.
Granting a group access to a repository
/groups grant <group-name> <path> <role>
Example — grant the backend-team group writer access to two repositories:
/groups grant backend-team */git/api-service writer
/groups grant backend-team */git/shared-lib writer
Every user who is a member of backend-team can now push to both repositories.
Revoking a group grant
/groups revoke backend-team */git/shared-lib
Removes the group grant. Individual user grants on the same path are not affected.
Full example: a shared project with a team
Here is a complete walkthrough for setting up a shared repository with different access levels for different people.
1. Create the repository
/git create api-docs
The admin who runs this command becomes owner automatically.
2. Add users
/users create alice password-for-alice
/users create bob password-for-bob
/users create carol password-for-carol
3. Grant individual access
Alice is a core contributor — give her write access:
/users grant alice */git/api-docs writer
Bob only needs to read the docs — give him read access:
/users grant bob */git/api-docs reader
Carol is co-maintaining the repo — give her ownership:
/users grant carol */git/api-docs owner
4. Each user clones with their own credentials
# Alice
# Bob
# Carol
Alice and Carol can push. Bob can only clone.
5. Using a group for the writing team
As the project grows, adding individual grants for each new writer becomes tedious. Move to a group:
/groups grant writers-team */git/api-docs writer
Now any user added to writers-team automatically gets write access. Individual explicit grants can be left in place or revoked — a user's effective role is the highest role from any matching grant (individual or group).
How grants interact with site stores
When /site create runs, it automatically records a grant like this:
alice */git/my-site writer
That is the grant that lets the site creator push content. It works exactly like a manually created grant. You can view it with /users grants alice, extend it to other users with /users grant, and revoke it the same way.
The site backend reads content directly from the repository's HEAD. Access control on the HTTP serving side (public vs authenticated) is a separate setting on the site entry, not a Git grant. Git grants only govern who can push and pull over SSH.