Audit log

Every change to a security setting, on the record

The audit log says who changed a secret, a ruleset, a webhook or a repository's visibility, when, and what, and names the agent or app if one acted. It says what changed, and never holds a secret's value.

What it records

Repositories, organizations and your own account

On a repository: secrets, mirrors and Sync now, rulesets, environments, webhooks, collaborators, its visibility and default branch, archiving, transfer and deletion, approved run secrets and deployments, AI provider keys, and caches cleared. On an organization: its secrets, webhooks, AI provider keys, Linear, SSO and SCIM, and its repositories transferred or deleted. On your own account: your external tokens, passkeys, SSO authorizations and personal repositories. Push and merge decisions are in push activity instead.

acme/invoices › Audit log
  • aliceset the secret DEPLOY_KEY for the environment productionsecret.set
  • claude-code for aliceadded a webhook to hooks.acme.examplewebhook.created
  • bobchanged the ruleset Protected branchesruleset.updated
  • bobsynced the mirror git@git.example.org:acme/invoices.git by handmirror.synced
  • carolapproved secrets for the run Deploy (#41)run.approved

Who and what

The person, and the agent acting for them

Each entry names the person, and the agent or app if one acted for them, so an agent's change is never taken for its person's own. It says what changed by name: a secret's name, a webhook's host, which fields. Never a secret's value, a token, a key or ciphertext.

GET /v1/repos/acme/invoices/audit
{
  "actor": "alice",
  "actorKind": "person",
  "agent": null,
  "scope": "repository",
  "target": "acme/invoices",
  "action": "webhook.updated",
  "subject": "hooks.acme.example",
  "details": { "id": 3, "fields": ["secret"] }
}

Who reads it

People only

A repository's log is for its administrators. An organization's is for its owners and site administrators, with its repositories' entries too unless they ask for repositories=false, and never through a token limited to some repositories. Your own is for you. Agents and apps can't read any of them.

~/invoices
$ curl -H "Authorization: Bearer $(bscope agent token --name claude-code)" https://api.branchscope.example/v1/repos/acme/invoices/audit
{"error":{"code":"forbidden","message":"agents and apps can't do this; a person does"}}
$ curl -H "Authorization: Bearer $LIMITED_TOKEN" https://api.branchscope.example/v1/orgs/acme/audit
{"error":{"code":"forbidden","message":"a token limited to some repositories can't read an organization's audit log"}}

Kept

Kept for good, unless the server says otherwise

Entries are kept for good. A server that should forget them sets AUDIT_RETENTION_DAYS, and older entries are deleted once a day. Each log reads newest first, in the web app and through the API, which can filter it by action, such as secret.

~
$ curl -H "Authorization: Bearer $BRANCHSCOPE_TOKEN" "https://api.branchscope.example/v1/orgs/acme/audit?action=secret&repositories=false"
{
  "data": [
    { "actor": "alice", "actorKind": "person", "agent": null, "scope": "organization",
      "target": "acme", "action": "secret.set", "subject": "NPM_TOKEN",
      "details": { "kind": "other", "repositories": null } }
  ],
  "nextCursor": null
}

See who changed what

Open a repository's Settings → Audit log, or your organization's, and every security setting change is there, with who made it.