Give coding agents a lane, not your GitHub token

TrustRail holds the GitHub App credential, evaluates a canonical software change, routes the exact subject for approval, and reconciles what GitHub says happened.

The governed path

Connect

Install the TrustRail GitHub App. Its private key stays in the control plane and installation tokens are minted only inside the execution boundary.

Scope

Bind the agent to an organization, environment, installation connection, repository, branch or ref, and registered action type.

Decide

Evaluate deterministic policy, runtime isolation, untrusted influence, traceable intent, anomaly risk, spend limits, and live containment state.

Approve

For escalated changes, show a semantic diff and bind the human vote to the exact authorization-subject digest.

Execute

Dispatch with the GitHub App installation token, write a TrustRail marker where the provider supports it, and retain only a redacted receipt.

Reconcile

Read back pull requests, commits, refs, releases, and deployments. A workflow dispatch remains manual when GitHub returns no run identifier.

What is enforced today

GitHub

Pull requests and merges

Create a marked pull request, merge an exact head SHA, and read the resulting object back from GitHub.

Refs

Push, force-push, delete, tag

Force is a distinct canonical action. Expected remote state is policy-visible; ambiguity is reconciled before any retry.

Delivery

Release, workflow, deployment

Publish releases, dispatch fixed workflows, and initiate deployments without exposing an installation token to the agent.

Evidence

Offline verification

Export the hash-chained audit ledger as NDJSON and verify its sequence, event hashes, and final chain hash without TrustRail.

Honest boundary: package.publish and secret.read have canonical schemas and policy governance but remain decision-only in the current registry. They are not represented as gateway-enforced provider actions yet. A GitHub workflow dispatch that times out after GitHub accepts it also requires manual resolution because the API returns no run id to bind safely.