DEV Community

Cover image for I Built a Git-Native SOC 2 Tool Because I Didn’t Want Another SaaS Bill
Abe Wheeler
Abe Wheeler

Posted on

I Built a Git-Native SOC 2 Tool Because I Didn’t Want Another SaaS Bill

I recently posted this on X:

Didn’t feel like paying a zillion dollars again for basic SOC 2 software, so I rolled my own this weekend.

100% file-based, uses Git for audit trails. Agents can absolutely cook on this thing.

That post got far more attention than I expected, so I thought developers might want a closer look at the idea and how it works.

The project is called filegrc. It is an open source, Git-native system for managing SOC 2 records and audit evidence.

The problem I wanted to solve

A lot of SOC 2 work is structured data wrapped in a web application:

  • Policies and their approval state
  • Controls, owners, and implementation details
  • Recurring security work
  • Risks, vendors, systems, and incidents
  • Evidence collected during an audit period
  • Links between all those records

Engineering teams already have a good system for reviewing structured text, tracking changes, assigning authorship, and preserving history.

That's Git.

I wanted to see what SOC 2 work would look like if the repository were the system of record.

The basic architecture

filegrc stores structured records as JSON and long-form content as Markdown.

A workspace looks roughly like this:

company-grc/
├── AGENTS.md
├── data/
│   ├── policies/
│   ├── systems/
│   ├── risks/
│   ├── obligations/
│   ├── evidence/
│   ├── audits/
│   └── workspace.json
├── package.json
└── README.md
Enter fullscreen mode Exit fullscreen mode

A policy record might contain fields such as:

{
  "schemaVersion": 1,
  "id": "policy-information-security",
  "type": "policy",
  "title": "Information Security Policy",
  "status": "draft",
  "ownerIds": ["person-policy-owner"],
  "approverIds": ["person-independent-approver"],
  "version": "1.0",
  "effectiveOn": "2026-08-01",
  "reviewCadence": {
    "mode": "calendar",
    "unit": "year",
    "interval": 1,
    "anchorDate": "2026-08-01"
  }
}
Enter fullscreen mode Exit fullscreen mode

The policy text lives beside it:

data/policies/policy-information-security.json
data/policies/policy-information-security.md
Enter fullscreen mode Exit fullscreen mode

The engine keeps data structured when it needs to validate, filter, calculate deadlines, or connect records. Policies, procedures, meeting notes, audit responses, and other long-form work stay in Markdown.

Why Git works well here

Git already records:

  • What changed
  • Who changed it
  • When the change entered the repository
  • The exact diff
  • The revision containing the change
  • The review that approved it

That removes the need for a second application-level change log.

Domain dates still need to remain explicit. A control test performed on July 10 needs a completedOn date, even if someone commits the record on July 11. Git records the repository change. The record describes what happened in the security program.

Keeping those concepts separate makes the history easier to inspect.

It also makes normal engineering workflows available:

git diff
git blame data/policies/policy-information-security.md
git log -- data/controls/control-access-review.json
Enter fullscreen mode Exit fullscreen mode

A reviewer can examine a policy change using the same tools they use for code.

The files still need a domain model

Putting JSON in Git is the easy part. The harder part is enforcing the relationships and lifecycle rules that make the records useful.

filegrc has a versioned model registry that defines:

  • Resource types
  • Required fields
  • Valid values
  • Relationships
  • Conditional requirements
  • Markdown content slots
  • Default UI metadata

The validator, CLI, browser forms, search index, and generated documentation all consume that model.

This means the browser and CLI do not have separate ideas about what a valid control or evidence record looks like.

You can validate an entire workspace with:

npm run validate
Enter fullscreen mode Exit fullscreen mode

The validator checks individual records as well as relationships between them.

For example, it can detect missing owners, broken references, invalid date ranges, incomplete policy events, missing Markdown, and evidence attachments that resolve outside the workspace.

Headless use is part of the product

I wanted coding agents to work with filegrc without learning the whole model from scratch.

A generated workspace includes agent instructions, and the CLI exposes model-driven guidance:

npx filegrc guide risk-assessment --json
npx filegrc list risk --json
npx filegrc references system-id --json
npx filegrc scaffold risk-assessment \
  --title "2026 Annual Risk Assessment"
Enter fullscreen mode Exit fullscreen mode

An agent can ask which fields a record requires, inspect valid relationship targets, scaffold a mutation, and run validation afterward.

Recurring and event-driven work is available through the CLI too:

npx filegrc obligations --json

npx filegrc trigger person-started \
  --occurred-on 2026-07-25 \
  --subject person-id

npx filegrc complete-action action-item-id \
  completion-record.json \
  --completed-on 2026-07-25
Enter fullscreen mode Exit fullscreen mode

The browser and CLI call the same domain functions, so an agent receives the same validation and calculations as a person using the UI.

That is what I meant when I said agents can cook on this thing.

A zero-dependency Node.js engine

filegrc browser experience

The filegrc engine uses Node.js built-in modules only.

It does not require a database, compilation step, bundler, or hosted service. It runs locally, in CI, or in a basic server environment with Node.js 20 or newer and Git.

The engine handles:

  • Workspace validation
  • CRUD operations
  • Search
  • Recurring obligations
  • Policy-triggered events
  • Program and audit readiness checks
  • Evidence packet generation
  • A local web interface

Writes are atomic, paths are checked against the workspace boundary, and CRUD commands do not create Git commits unless the user explicitly asks for one.

What filegrc does not replace

filegrc manages GRC records and audit evidence. It does not replace infrastructure logging, identity management, backups, endpoint protection, monitoring, training, or incident detection.

Those systems remain the authoritative sources.

filegrc catalogs them, records how evidence should be collected, and connects their exports or reports to the relevant controls and audit work.

It also does not decide whether a company is compliant. The organization has to operate its controls, and the independent CPA firm still evaluates the evidence and performs the audit.

Try it locally

You can create a workspace with:

npx create-filegrc@latest company-grc
cd company-grc
npm run validate
npm run serve
Enter fullscreen mode Exit fullscreen mode

The generated repository starts with draft records and setup work. The starter content is a proposal, not a claim about how your company operates.

Review it, change it, and commit the version that reflects reality.

GitHub logo Sunpeak-AI / filegrc

Git & file-based SOC 2

filegrc

Run a SOC 2 program as files in Git.

filegrc gives a founder-led engineering team one place to adopt policies, implement controls, test External Evidence collection, run recurring compliance work, and prepare an audit. JSON holds structured records, Markdown holds long-form work, and Git supplies the change history.

There is no separate application database. The repository is the program, so engineers and agents can use the same data through the web app, a text editor, or the CLI.

filegrc SOC 2 program overview

Why it exists

SOC 2 work tends to scatter across documents, calendars, tickets, screenshots, and the auditor’s request list. That makes it hard to answer basic questions: What is due? Which policy requires it? What changed during the audit period? Is the evidence complete?

filegrc keeps that work connected:

  • A starter Security program links criteria references, policies, planned controls, owners, and schedules.
  • Work Queue turns policy timing into upcoming, due, and…




Which security and compliance records would you keep in Git, and which ones belong in their source systems?

Top comments (0)