Skip to content
GitmoapdocsBeta
Concept· Why does it work like that?Draft

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:

MarkingWhat it meansExamples
audited · mutationevery call is recorded — success, refusal and failure alikecreating a repository, merging, changing access, a git push
audited · sensitive_reada read that exposes a credential surface, recorded each timelisting personal or service-account tokens, reading a service account, reading a provider connection or the single sign-on connection, listing your connected apps
exemptnot recordedevery 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:

ViewHoldsWho can read it
An organizationactions whose target is a group or repository anywhere in it — settings, visibility, membership, branches and tags, pushes and fetchesan Owner of the top-level group, and platform administrators
A repositorythe same, narrowed to one repositoryan Owner of that repository
Platform-wideeverything, including actions on a single merge request, work item, webhook or token, filed under whoever acted, and each person's sign-insplatform 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.