Setup · about 10 minutes

Installing it is not the finish line. Watching a merge get held is.

Inviolable reports a check result. What actually holds a merge is your repository's branch protection — and we have no way to see whether you've configured it. So setup doesn't end when the app is installed. It ends when you've made a merge get held, once, with your own eyes.

Note: Inviolable is in development and not yet available. Steps 1–2 describe the intended flow. Steps 3–4 are GitHub's own mechanics and work today — you can use them to protect a repository with any status check, including one you write yourself.

Before you start

  • Admin access to the repository (you'll be editing branch protection)
  • A decision about who holds bypass — at least one person must be able to merge past a failing required check. This is your escape hatch if we ever go down, and setup is not complete without it
  • Two minutes at the end for the test. Don't skip it. It is the only part of this page that proves anything

The four steps

Step 1 · install

Install the app on the repository

Inviolable requests four permissions and no more: Pull requests: Read, Checks: Read & Write, Contents: Read, Metadata: Read.

Read that list on GitHub's install screen before you approve it. Contents: Write is not there and never will be — this app cannot modify your code, and that isn't a policy we're asking you to trust, it's a permission we don't hold.

Step 2 · declare

Commit .inviolable.yml to the default branch

List the paths that no agent-authored change should reach without a human looking at it.

version: 1
protected:
  - firestore.rules          # security rules
  - .github/workflows/**     # whoever controls CI controls everything
  - src/billing/**           # bugs here cost real money
  - CLAUDE.md                # the agent's own instructions
  - ".env*"
# .inviolable.yml itself is always protected, whether you list it or not

What goes in this list is your call, and it's the part we can't help with. A path you don't list isn't protected. Start narrow — five paths you'd be genuinely unhappy to see changed quietly — and add to it when something makes you nervous.

Step 3 · enforce

Make the check required — this is the manual step

In Settings → Branches → Branch protection rules (or Rulesets) for your default branch, enable Require status checks to pass before merging and add Inviolable to the list.

Until you do this, nothing is enforced. The check will still go red — you'll see it on the pull request — but the merge button will work anyway, and we won't know. We don't request the permission that would let us read your branch protection settings, so we can't warn you, and we won't pretend otherwise.

Why we make you do this by hand: automating it would mean asking you for admin-level permissions on your repository. For a tool whose entire argument is that guards should hold as little power as possible, that trade isn't available to us. The friction is the price of the permission we don't take.

Step 4 · prove it

Make it go red. Watch the merge get held.

This product's whole argument is that you shouldn't trust a guardrail's self-report. It would be strange to then ask you to trust ours. So:

  1. Create a branch and change one line in one of your protected files — a comment is fine
  2. Open a pull request
  3. Wait for the check
Inviolable — Failing · protected path touched: firestore.rules
🔒Merging is blocked · required status check has not succeeded

If you see both lines, you're set up. The red check is us. The held merge is GitHub, doing what your branch protection tells it. Close the pull request and delete the branch — you're done.

If the check goes red but you can still merge, you are not protected. Step 3 didn't take effect. Go back and confirm the check name matches exactly, and that the rule applies to the branch you're targeting. Do not skip past this — a red check on a mergeable PR is worse than no check at all, because it looks like protection.

Re-run the test every few months

Branch protection lives on your side and can change without us knowing — a rule gets renamed, a repo gets migrated, someone tidies up settings. The two-minute test is the only way either of us finds out. Put it in the calendar quarterly.

Do it again after any of these: changing branch protection or rulesets, renaming the default branch, moving the repo between accounts or organizations, or converting it between public and private.

Break glass: what to do if Inviolable is down

The check fails closed by design, which has a consequence we'd rather state plainly than bury: if our service is down, your check never reports, and GitHub holds your merges. We won't quietly flip to passing to get you unstuck — a guard that stops guarding when it's inconvenient is the exact failure this product exists to argue against.

So the way out is on your side, and it's why Step 3 asks you to nominate a bypass holder:

  1. Check status.inviolable.dev to confirm it's us and not your configuration (planned — not live yet)
  2. A bypass holder merges deliberately. GitHub records who did it and when, in your audit log — the record stays with you, not with us
  3. When we're back, re-run the Step 4 test to confirm normal behaviour has resumed

If losing the ability to merge during an outage is unacceptable for a given repository, that's a legitimate reason not to make the check required there — or not to use this tool for it. We'd rather you decide that up front than find out during an incident.

Before you rely on this

Please read what Inviolable does not catch. The short version: it answers exactly one question — does this pull request's diff contain a path you listed? — and reports the answer. It doesn't judge whether a change is good, it doesn't see changes that never open a pull request, and it can't stop someone with bypass who decides to merge.

YoursOurs
Deciding which paths matter
Configuring branch protection
Holding bypass, and using it deliberately
Running the test
Reading the PR diff
Matching it against your list, deterministically
Reporting pass or fail — and reporting fail when we can't verify
Telling you loudly when we're broken

日本語での手順

Step 1:Appをリポジトリにインストールします。要求する権限は Pull requests: Read / Checks: Read & Write / Contents: Read / Metadata: Read の4つだけです。Contents: Write は含まれません——承認画面でご自身の目でご確認ください。

Step 2:デフォルトブランチに .inviolable.yml をコミットし、保護したいパスを列挙します。何を書くかはお客様の判断で、書き漏らしたパスは保護されません。

Step 3Settings → Branches でブランチ保護ルールを開き、「Require status checks to pass before merging」に Inviolable を追加します。この設定をしない限り、何も止まりません。チェックは赤くなりますが、マージボタンは効いてしまいます。当Appはブランチ保護の設定を読む権限を持たないため、この状態を検知してお知らせすることができません。

Step 4:保護ファイルを1行変更したPRを作り、チェックが赤くなり、GitHubがマージを止めることをご自身の目で確認してください。赤くなるのにマージできてしまう場合、保護は効いていません。Step 3 に戻り、チェック名の一致と対象ブランチをご確認ください。

この製品の主張は「ガードレールの自己申告を信用するな」です。ですから、当社の申告も信用しないでください。一度、自分の手で赤くしてみてください。

また、当社の障害時はチェックが報告されずマージが止まります。勝手に緑にして通すことはしません。そのため、ブランチ保護のバイパス権を持つ方を必ず1名以上置いてください。脱出の判断はお客様の側にあります。