Audit Logs, Security Policies, Compliance Evidence, Repository Governance, and Enterprise Controls: Concepts, Architecture, and Mental Model
Build a mental model that connects GitHub policy, enforcement, audit events, external evidence retention, exceptions, and periodic governance review.
Learning objectives
- Explain the actor/action/resource/time/source model of an audit event.
- Distinguish audit search, export, API retrieval, and enterprise streaming.
- Relate SECURITY.md, CODEOWNERS, rulesets, security configurations, access policy, and audit evidence without treating them as interchangeable.
- Separate compliance evidence from actual security outcomes.
- Design evidence ownership, exception expiry, review cadence, and external retention.
1. The problem: “we have a policy” is not evidence that a control operated
Chapter 28 designed who should be allowed to administer repositories, teams, and organization settings. Chapter 29 asks the next operational question: how would another engineer, an incident responder, or an auditor prove what policy existed, who changed it, when it changed, and whether an exception was deliberate? A markdown policy may explain intent. A ruleset may enforce part of that intent. An audit event may record a setting change. A retained export may preserve the event after GitHub's native window. None of those items alone proves that the system is secure.
Governance becomes credible when five things line up: a control objective, an enforceable or reviewable GitHub configuration, an accountable owner, evidence showing the control's operation, and an exception process with a reason plus expiry. The evidence must be interpretable even during an incident in which the GitHub account itself is part of the investigation.
2. Read-only inspection comes before governance changes
Start with the repository and account you actually intend to reason about. A Git remote is only a Git transport destination; rulesets, security configurations, organization membership, and audit logs are hosted GitHub resources. The following commands are read-only and do not expose authentication secrets.
git remote -v
gh auth status
REPO="OWNER/c29-governance-evidence-lab"
gh repo view "$REPO" --json nameWithOwner,visibility,defaultBranchRef,url
gh api -H "X-GitHub-Api-Version: 2026-03-10" "repos/$REPO/rulesets" --jq '.[] | {id,name,enforcement,target}'
gh api -H "X-GitHub-Api-Version: 2026-03-10" "repos/$REPO/contents/SECURITY.md" --jq '{name,path,sha}' 2>/dev/null || echo "SECURITY.md not present"
A missing file or empty ruleset list is a state observation, not a security conclusion. Likewise, an audit query returning no rows does not prove that an action never occurred. Scope, permissions, event family, retention window, and product plan all affect what can be seen.
3. Mental model: policy → enforcement → action → evidence → retained proof
flowchart TD
A["Control objective"] --> B["Policy document"]
A --> C["GitHub enforcement"]
B --> D["Human decision"]
C --> E["Hosted action"]
D --> E
E --> F["Audit event / Git evidence"]
F --> G["Time-bounded query or export"]
G --> H["External retained evidence"]
H --> I["Review / incident / audit"]
I --> J["Exception or control correction"]
J --> A
The arrows are a control loop, not a claim that every GitHub action emits every kind of evidence. A control objective such as “production changes require review” may be described in policy, enforced by a ruleset, exercised by a pull request, recorded through check/review state and selected audit events, exported or retained, and later reviewed. An exception feeds back into policy only if it has an owner, reason, approval, expiry, and follow-up.
4. What an audit event represents
An audit event is a structured record of an
auditable action in an organization or enterprise. The event name
normally combines a category and operation, such as
team.add_repository or
repository_ruleset.create. The useful mental model is:
| Field family | Question it answers | Example |
|---|---|---|
| Actor | Who initiated the action? | actor, actor ID, bot/agent indicators |
| Action | What auditable operation occurred? | team.update_repository_permission |
| Resource/target | What organization, repository, team, user, or policy changed? |
org, repo, team,
user
|
| Time | When did GitHub record the event? | @timestamp, created_at |
| Source context | How did the request reach GitHub? | request ID, user agent, programmatic access type, token metadata where emitted |
| Change metadata | What important before/after detail is recorded? | old/new permission, ruleset conditions, enforcement state |
| Event identity | How can a retained copy be correlated/deduplicated? | _document_id where present |
Not every event contains every field. Preserve the original event before normalizing it so an investigation can revisit fields your first report did not consider important.
5. Search, export, REST retrieval, and streaming are different operating surfaces
The organization audit-log UI is owner-only. Current GitHub documentation describes auditable organization activity within the last 180 days; the default view focuses on recent activity, and Git-event retention is much shorter at seven days. The organization REST audit-log endpoint is documented for GitHub Enterprise Cloud and requires organization-owner authorization. Its default response is up to 30 recent web events, supports cursor pagination and a maximum page size of 100, and has a dedicated rate limit of 1,750 queries per hour per user and IP.
| Surface | Best use | Important boundary |
|---|---|---|
| Organization UI search | Interactive investigation using qualifiers such as actor/action/repo/created | Owner access; do not interpret empty results without checking scope/window |
| UI export | Small, filtered JSON/CSV evidence set | Current export hard limit: 100 MB compressed or 10 minutes processing |
| REST audit-log endpoint | Structured automation and pagination | Enterprise Cloud organization API; explicit version header; owner permission |
| Enterprise streaming | Continuous off-platform retention and SIEM correlation | Enterprise owner; currently public preview; at-least-once delivery means duplicates are possible |
The old GraphQL audit-log objects are not the path to build new automation around: GitHub marked that audit-log GraphQL surface for removal on April 1, 2026. This chapter uses the current REST/UI model.
6. Policy documents, ownership files, enforcement, and security configurations
SECURITY.md tells people which versions you support and
how to report vulnerabilities. It is human-readable policy and is
available without purchasing GitHub Secret Protection or Code
Security. CODEOWNERS maps paths to responsible people
or teams, but ownership metadata alone does not block a merge. A
ruleset can enforce review, signed commits, required checks, or
other repository rules. Repository rulesets are available for public
repositories on GitHub Free; organization-wide rulesets require
GitHub Team or Enterprise.
A security configuration is an organization/enterprise collection of security-feature settings that can be attached to repositories. The configuration object and the individual capabilities it controls are separate availability questions: public repositories can use many security capabilities for free, while private/internal Code Security or Secret Protection capabilities may require Team/Enterprise plus the corresponding product. An access policy answers who may use a resource or feature. None of these is a replacement for the others.
7. Compliance evidence is not a security outcome
A report that says “ruleset active,” “CODEOWNERS present,” and “audit event retained” can establish that configured controls existed and that selected actions were recorded. It cannot prove the code has no vulnerability, that reviewers understood a malicious change, or that an administrator never used an unlogged external system. Evidence supports a claim with a defined scope. A mature control states that scope rather than upgrading evidence into certainty.
8. External retention and chain of custody
If the GitHub organization under investigation is the only place evidence exists, loss of owner access or compromise of the account can obstruct the investigation. Enterprise streaming solves part of that problem by copying events to an external system, but even a small organization can practice the underlying discipline: record the exact query and retrieval time, save the raw response, calculate a digest, restrict who can overwrite the archive, normalize into a report without discarding the raw source, and hash the normalized output as well.
A SHA-256 digest is an integrity check for the bytes you retained; it is not proof that GitHub originally emitted those bytes. Chain of custody also needs provenance: who collected the export, from which account/query, at what time, using what tool/version, and where the immutable or write-restricted copy is stored.
9. Ownership, exceptions, periodic review, and control drift
Every governance control needs an owner who can explain the requirement and approve changes. Every bypass or exception needs a reason, narrow scope, approver, start time, expiry, and compensating control. A quarterly review should compare the declared policy against current repository rulesets, CODEOWNERS, organization access, security configurations, and recent audit events. Control drift is the gap between what the policy says and what the hosted configuration actually does.
10. Why this matters in DevOps
Delivery systems change through automation. A release can be secure at noon and exposed at 12:05 after a ruleset, environment, team permission, secret-scanning setting, or App permission changes. Governance therefore cannot be a once-a-year document review. It is an evidence-producing operating loop around the same GitHub resources that CI/CD depends on.
11. Safe read-only mini-lab
Create no organization and no privileged token yet. Save this clearly synthetic event and inspect its structure. It mirrors documented audit-event field names but does not claim to be an event from your account.
[
{
"_document_id": "fixture-team-001",
"@timestamp": 1787175000000,
"action": "team.add_repository",
"actor": "learner-example",
"org": "octo-c29-fixture",
"repo": "octo-c29-fixture/service-api",
"team": "octo-c29-fixture/release",
"permission": "push",
"request_id": "REQ-FIXTURE-001"
}
]
Before normalizing, answer: which field identifies the operation,
which fields describe the resource scope, and which field would you
preserve for deduplication? Then calculate a local digest of the
fixture file with sha256sum audit-fixture.json (or
Get-FileHash -Algorithm SHA256 in PowerShell). This is
the first chain-of-custody habit the rest of the chapter will use.
Knowledge check
Why is SECURITY.md not an enforcement control by itself?
It communicates policy and reporting instructions, but GitHub does not interpret the prose as a branch, access, or merge rule. Enforcement needs a machine-enforced surface such as a ruleset, branch protection, permissions, or a security product setting.
What is the difference between an audit event and retained compliance evidence?
The audit event is GitHub's structured record of an auditable action. Retained compliance evidence is the controlled copy plus collection context, hashes, normalization, ownership, and retention information used to support a defined control claim.
Why does enterprise audit streaming need deduplication logic?
GitHub currently documents the stream as at-least-once delivery, so the receiver can receive duplicate events. Preserve event identifiers and make downstream processing idempotent.
Can an empty audit query prove an action never happened?
No. First verify time range, event family, query filters, permissions, plan/deployment, retention, and whether the action is audited at all.
Which is more durable for a long incident: relying only on GitHub-native retention or retaining an independently controlled export/stream?
An independently controlled copy is more resilient because the platform account under investigation is not the sole evidence store. GitHub-native logs remain valuable, but they are time-bounded and access-dependent.
Summary
GitHub governance is a traceable control system: policy describes intent, hosted controls enforce what can be automated, audit and Git evidence record selected actions, external retention preserves evidence beyond a platform/account failure, and review/exception processes keep the control current. In Lesson 2 you will build a disposable evidence repository and turn realistic raw events into a normalized, hashed evidence packet.
Further reading — current primary sources
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.