Audit
Overview
Every change made through Gitmoap is recorded — who made it, to what, when, and whether it worked — along with every sign-in and a short list of reads that expose credentials. The record is append-only and tamper-evident, so you can prove afterwards that nothing in it was edited, removed or reordered.
Ordinary reads are not recorded. Viewing a repository, listing commits or opening a merge request leaves no trace, because a log in which browsing outnumbers acting is a log nobody reads.
How it works
What each operation's marking means
The API reference marks every operation with whether calling it is recorded:
| Marking | What it means | Examples |
|---|---|---|
audited · mutation | every call is recorded — success, refusal and failure alike | creating a repository, merging, changing access, a git push |
audited · sensitive_read | a read that exposes a credential surface, recorded each time | listing personal or service-account tokens, reading a service account, reading a provider connection or the single sign-on connection, listing your connected apps |
exempt | not recorded | every ordinary read, and the few writes that change nothing you own, such as validating a pipeline definition |
Sign-ins are recorded too, and so are git clones and fetches.
A refused attempt is still a record. A 403 on a delete is written with an outcome of denied, and a request that failed with an outcome of failure, because a rejected attempt is often the most valuable line in a security review. A dry run of an access, team or role change, or of a commit, is not recorded: it changed nothing.
What a record holds
Each record names the actor — a person, a service account or a pipeline — with their name and email as they were at that moment, how they authenticated and with which token, the action and its target, the outcome and HTTP status, the time to the microsecond, and the request id. A request made by an AI agent through the MCP server also names the tool and the client application.
Records are written just after the request finishes, so one usually appears within a second of the action.
Append-only, and tamper-evident
Nothing in the log can be edited or deleted by anyone, through any interface. Each record is sealed with a hash over its own contents and the hash of the record before it, so changing one character, removing a record or swapping two breaks every hash that follows.
Verifying replays that chain over a window of months and reports the first position where it no longer adds up. A clean result proves that nothing recorded has been altered since. It does not prove that everything that happened was recorded: a crash in the instant between a request finishing and its record being written loses that one record without leaving a gap. Verifying writes nothing, so you can schedule it.
Who can read which log
A record files under the most specific thing the request named, and that decides which view shows it:
| View | Holds | Who can read it |
|---|---|---|
| An organization | actions whose target is a group or repository anywhere in it — settings, visibility, membership, branches and tags, pushes and fetches | an Owner of the top-level group, and platform administrators |
| A repository | the same, narrowed to one repository | an Owner of that repository |
| Platform-wide | everything, including actions on a single merge request, work item, webhook or token, filed under whoever acted, and each person's sign-ins | platform administrators |
Reading needs audit:read on a token, and verifying needs audit:verify. Owner is a hard floor: making a group public opens nothing here.
Related
- Audit logreading, filtering and verifying the log, and which view holds which record
- Access tokensthe token id every record carries, and what listing tokens records
- Dry runspreviews that leave no record
- AI agents and the MCP serverwhat a record says about a change an agent made