Skip to content

CI merge-gate

Proof is only useful if it is enforced. The merge-gate turns the evidence bundle into policy: a change does not merge unless a valid, re-verified attestation exists for it.

Fail-closed by design

The gate never trusts the mere presence of attestation files — it re-runs verification every time. For the change at HEAD:

  • every DSSE verdict must verify against the agent's public key, and
  • the receipt it names must be anchored with a transparency-log inclusion proof that verifies under the pinned log key and binds that same receipt.

Any present-but-invalid verdict, any receipt without a verifiable inclusion proof, or no attestation at all → block. It fails closed:

merge-gate: ALLOW  — HEAD is backed by a valid, re-verified attestation (did:keri:EGzTx…)
merge-gate: BLOCK  — no valid, re-verified attestation for HEAD

The command exits 0 to allow and 1 to block, so it drops straight into any CI:

python3 tools/ci_merge_gate.py    # exit 0 = allow, exit 1 = block the merge

Wire it into GitHub Actions

The workflow checks out the change and its two siblings (the gate and the signer), builds the SDK from source, then runs the full chain under set -e — so a blocked merge-gate fails the job:

name: merge-gate
on:
  pull_request:
  workflow_dispatch:

jobs:
  merge-gate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { path: auths-curve }
      - uses: actions/checkout@v4
        with: { repository: auths-dev/auths, path: auths }
      - uses: actions/checkout@v4
        with: { repository: bordumb/recurve, path: recurve }
      - uses: actions/setup-python@v5
        with: { python-version: "3.12" }
      - uses: dtolnay/rust-toolchain@stable
      # The gate rebuilds the SDK from source so it measures this exact code.
      - name: Build the auths native extension
        working-directory: auths/packages/auths-python
        run: |
          cargo build --lib
          cp target/debug/lib_native.so python/auths/_native.abi3.so
      - name: Gate, sign, verify, and enforce
        working-directory: auths-curve
        run: bash demo.sh

Make it required

Add the check to your branch protection so no pull request can merge without it:

  1. Settings → Branches → Branch protection rules for main.
  2. Enable Require status checks to pass before merging.
  3. Select the merge-gate check.

From then on, a change merges only when an independent, re-verified proof says it passed — the green button is backed by evidence anyone can re-check, not by trust.

Verify the same thing locally

The gate the workflow runs is the one you can run by hand: python3 tools/ci_merge_gate.py. Same fail-closed logic, same exit codes — CI just runs it for you on every pull request.