CI/CD
Gate production deploys on ORBIT approval.
The same loop that governs agent actions — request, policy, decision, signed receipt, verification — applied to your deploys. A deploy pauses until ORBIT approves it, and your pipeline verifies the signed approval before anything in your cloud changes. Shipped today for GitHub Actions; other paths are listed at the bottom.
What deploy approval is
You add one reusable step — orbit-approve — to your deploy job, immediately before the step that changes your cloud. That step asks ORBIT to approve this exact deploy, waits for the decision, and lets the deploy run only when ORBIT approves and the signed approval receipt matches the deploy in front of it. A missing, denied, expired, or mismatched approval fails the deploy closed: it never runs.
This is configuration plus install — you never need ORBIT source access, and you store no static cloud keys: the runner proves who is deploying what, from where, with a short-lived GitHub identity token minted per run.
What happens on every deploy
- Request.The step sends ORBIT the immutable facts of the deploy: repository, commit, workflow run, environment, who triggered it, the artifact digest, and the plan hash — attested by the runner’s identity token, so they can’t be forged.
- Policy decides. ORBIT applies your policy: auto-approve, or pause for a human approval in the app, exactly like an agent step-up.
- Signed receipt. On approval, ORBIT signs a receipt bound to those exact deploy facts.
- Verify before mutation. The pipeline verifies the receipt — authentic signature, approved verdict, fresh, and bound to the exact commit, environment, and artifact it is about to ship — before any cloud change.
- Fail closed. Anything missing, denied, expired, or mismatched stops the deploy.
Because the receipt is bound to the deploy’s facts, an approval for one commit or artifact can’t be replayed to ship a different one.
What you configure
orbit-api-url— your ORBIT gateway base URL (must behttps).orbit-api-key— your ORBIT API key, stored as a CI secret, never a literal.oidc-audience— the token audience your ORBIT tenant expects for deploy approvals.environment— the deploy environment; must equal the job’senvironment:.artifact-digestandplan-hash— what you are deploying, assha256:<hex>values your build produces.
Everything else (repository, commit, workflow, run, actor) defaults from the run itself and must match the identity token’s claims. The step also needs the orbit-verify binary on the runner to check the receipt — install a pinned version in a prior step, and pin the Action itself by commit.
A minimal workflow
jobs:
deploy:
runs-on: ubuntu-latest
environment: production # must equal the 'environment' input
permissions:
id-token: write # lets the runner mint its identity token
contents: read
steps:
- uses: actions/checkout@v4
# 1) Put a pinned, checksum-verified orbit-verify on PATH.
# 2) Build your artifact; compute its digest and your plan hash.
# 3) Gate on ORBIT approval. This is the fail-closed step.
- name: Gate on ORBIT deploy approval
uses: adavidson510/orbit-governance/integrations/orbit-approve@<pinned-sha>
with:
orbit-api-url: https://api.your-orbit.example
orbit-api-key: ${{ secrets.ORBIT_API_KEY }}
oidc-audience: orbit-deploy-approve-prod
environment: production
artifact-digest: sha256:${{ steps.build.outputs.digest }}
plan-hash: sha256:${{ steps.plan.outputs.hash }}
# 4) Your real deploy. Runs ONLY if the gate above succeeded.
- name: Deploy
run: ./deploy.shYour deploy is the next step, so a failed gate stops the job before the deploy is reached. Do not add continue-on-error to the gate step — that would defeat the fail-closed contract.
The fail-closed contract
The gate stops the deploy — never a silent pass — when:
- the runner can’t mint its identity token, or the API key is missing;
- ORBIT rejects the request (including facts that don’t match the attested token);
- the decision is denied, expires, or the wait for a human decision times out;
- the approval has no signed receipt, the signature doesn’t verify, the receipt isn’t fresh, or it binds a different deploy than the one the runner is about to perform;
- ORBIT or the verifier is unreachable — an unavailable dependency is never a pass.
Keep the ORBIT receipt alongside your cloud provider’s own deploy logs: together they show approved-and-verified intent plus the actual change.
Upcoming paths — not yet available
- GitHub App / deployment protection rule.An install-from-GitHub integration that gates GitHub’s own deployment environments without editing workflow files.
- Non-GitHub CI(GitLab, Jenkins, Buildkite, and others) — the same flow authenticated by your CI provider’s workload identity. Until it ships, the deploy-approval request path accepts GitHub Actions identity only.