Reference
Security guarantees
What Babbit guarantees, for a security or compliance reader. Each guarantee names what makes it true, and every exception is stated where it applies.
How to read this page
Each section states guarantees as plain sentences. Where a guarantee has an exception or isn't fully enforced yet, the page says so in the same section. Nothing here describes intent that isn't built; designed-but-unbuilt features are listed in What's planned.
The MCP looks up; it never trusts the call
- An agent writes the spec, records evidence, uses a secret or starts a change only through the Babbit MCP. There is no other write path for an agent.
- Babbit mints one token per run, bound to its agent or client, the project, the change, the workspace and the tier. A call carries the token and the tool's own arguments, nothing else.
- Before any tool runs, the MCP refuses a token whose workspace has ended, a tool the caller isn't granted, and a session that wrote the code asking to record its evidence or promote it.
- Change state, approved proposals, reviews, evidence and approvers are looked up by change id, never taken from the call.
- Every call, refused or not, is one row in a log that refuses deletes and updates.
Evidence is a run bound to a commit
- Evidence is one run of one test at one commit, recorded by run id from runs Babbit's own runner made at the head of the pull request, in the repository the test lives in.
- Each row records the run, the test and its repository, the commit, the hash of the scenario's line, and a screenshot's hash when there is one.
- A new head in that repository, or an edited line, voids the evidence.
- Every attempt is kept. A fail and a pass at one commit is flaky and not verified.
- A new or edited scenario's test must fail at the change's base commit. Green there is not evidence.
- Screenshots are stored and cited by the hash of their bytes, never by a link.
- A deploy is recorded from what the provider reports, never from what a promotion meant to ship. A deploy counts only after its smoke scenarios pass, and a failure rolls back every service of the release.
A change is identified by its pull requests
- A change, a release, the base snapshot and every other record move only by an event a row of one state table allows, checked against the record. A job starts because a record entered a state, never on a clock. A redelivered webhook does nothing twice.
- Babbit merges only through its land step, which reads the
newdev/shape,newdev/evidenceandnewdev/setcheck runs its own runner posted on each pull request head. - The GitHub app never writes the default branch and doesn't hold the
workflowspermission. - An approval binds to the content of the approved lines, not to a commit. The spec pull request lands only while its head renders exactly those lines. Comments merge on their own branch and can't alter an approved change.
- A push that isn't fully explained by the merged pull requests of its change is drift, recorded with its pusher. A forced push is read from before to after.
- No workspace holds a Git credential. Code leaves as a diff that the app commits under
change/ornewdev/, and any other branch is refused.
Where a secret can and cannot be
- A value is written once, sealed, and never read back by a person or an agent.
- No value enters a snapshot, a workspace or a transcript, with the one exception below. A workspace holds opaque handles.
- The egress proxy resolves a handle only for the workspace it was issued to, in the tier that workspace is bound to, and only on a host the secret declares. Never GitHub or a package registry. It records the name, version and host of each use, and scrubs the value from the answer.
- Transcripts and run logs are scrubbed by exact match against live values before anything keeps them.
- An agent gets a handle only for a name a service of its change declares, in a tier its settings let it act in. An outside client never gets one.
- A secret that answers both preprod and prod must be a read-only API key; anything that acts is one record per tier.
- Rotation lists every live holder of the old version. Deletion is refused while a declared reader would be left with nothing.
The exception: model credentials for Claude Code and Codex
When a session runs in Claude Code or Codex, the harness needs its vendor credential, such as a Claude subscription token or an OpenAI key. For those sessions, and only those, the credential is in the workspace: readable by the agent and by anything it runs there.
What still holds:
- The vault releases the credential only into the workspace made for that session, and records it.
- No other workspace, including Verify's, gets it.
- The agent runs as a firewalled user whose only way out is the egress proxy, which lets it reach the vendor's own hosts and nothing else, logging every connection.
- Transcripts are scrubbed of the credential, and no committed work may carry it.
What it costs: tokens such a session spends are counted by the vendor, not by Babbit, so the stop rule's token limit can't see them live. Time and inactivity limits still apply.
Who may do what
- An approval counts only when the project's policy lets that person give it, looked up for the change by id. On drift, the pusher's approval follows the Approve own drift permission.
- Someone who left holds no role in any check.
- Production is approved only by someone with the Promote to prod permission.
- Every write to the organization, memberships, permissions and invites is a row in an audit log that refuses updates and deletes.
- An invite joins one recipient, once, before it expires. Its token is kept only as a hash.
- Sign-in uses GitHub. The GitHub token is read once and never kept. The browser holds an opaque session id; Babbit keeps only its hash and refuses it after 30 days.
- A person reads a project only while they hold a role on it. Any other project reads as no such project.
- Every caller's request rate is bounded, and a browser's write from another site is refused before any route reads its cookie.
Where traces live, and for how long
- Traces are never in Git. Each batch is scrubbed before it's stored.
- A field a contract marks as a person's data is kept as its shape, never its value, in every tier.
- Preprod traces are kept for 14 days and prod traces for 30. A person can be forgotten across every tier in one request; the counts on a box name no one and stay.
Onboarding
- Onboarding reads source read-only and builds the base snapshot from a repository archive, so the snapshot holds no credential; the build refuses one before anything is saved.
- Drafts are agent-written. Source ranges and the tree's structure are checked, but no second model judges whether each claim follows from its evidence. No probability or passing test is invented. The spec is committed only after the owner approves.