diff --git a/README.md b/README.md index 4dd9473..2bce28d 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,12 @@

Deploy Gate

- AI tried to deploy. It got blocked. + Block AI deploys until a human signs.

- No AI action executes without an explicit human signer.
- One workflow. One secret. Works on your first PR. + AI agents can open PRs. They should not deploy to production.
+ This GitHub Action enforces that boundary.

@@ -21,23 +21,23 @@ --- -## How it works - -``` -PR opened → ❌ Deploy blocked → Human signs → ✅ Deploy proceeds -``` +## See it in action

Deploy Gate blocking a PR — approval required

-Open a PR. Deploy Gate blocks the merge. Click the approval link. Sign. Merge proceeds. Receipt recorded. +``` +PR opened → ❌ Blocked → Human signs → ✅ Merge allowed +``` -**Takes ~3 minutes to install. One secret.** +Open a PR → Deploy Gate blocks it → click approval link → sign → merge proceeds → receipt recorded. --- -## Install +## Quickstart + +Add to your workflow: ```yaml # .github/workflows/deploy-gate.yml @@ -52,187 +52,89 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: permission-protocol/deploy-gate@v1 + - uses: permission-protocol/deploy-gate@v2 with: pp-api-key: ${{ secrets.PP_API_KEY }} ``` -1. Get API key from [app.permissionprotocol.com](https://app.permissionprotocol.com) -2. Add secret: `gh secret set PP_API_KEY -b "pp_live_..."` -3. Add workflow above -4. Open a PR → see it blocked → approve → merge - -**[Full install guide →](./INSTALL.md)** - ---- - -## Why this exists - -AI agents can deploy code, delete data, and modify infrastructure. - -Today, they often do this with no approval, no accountability, and no audit trail. That's a production risk. - -"Approved" is a mutable DB flag. An agent, a backend, or a bug can flip it. There's no proof a human authorized *this specific action* with *these exact arguments*. - -Deploy Gate enforces: +1. Get API key → https://app.permissionprotocol.com +2. Add secret: +```bash +gh secret set PP_API_KEY -b "pp_live_..." +``` +3. Open a PR → watch it get blocked → approve → merge -- ✅ Explicit human signer (Ed25519) -- ✅ Signature bound to exact args (commit, repo, environment) -- ✅ Single-use receipt (replay fails) -- ✅ Tamper-evident — any post-signing mutation fails verification +**Takes ~3 minutes. One secret.** -It does not trust database state. Only the signed receipt. +👉 [Full install guide →](./INSTALL.md) --- -## Flow - -

- PR Created to Deploy Gate flow -

+## What it does -``` - PR opened - │ - ▼ - Deploy Gate verifies/creates request - │ - ├── Receipt exists + valid ──────────────► ✅ Merge OK - │ - └── No receipt ──────────────────────────► ⏳ Blocked + PR comment with approval link - │ - ▼ - Human approves in dashboard - │ - ▼ - Re-run CI → ✅ Merge OK -``` +- Blocks risky PRs with a required status check +- Posts a PR comment with a direct approval link +- Sends the reviewer to Permission Protocol to approve and sign +- Unblocks the PR instantly after approval +- Produces a tamper-evident approval record --- -## PR Comments - -Deploy Gate posts directly on your PR: - -Approval required: -``` -⏳ Permission Protocol: Approval required - Review & approve → https://app.permissionprotocol.com/pp/deploy-requests/{id} -``` +## Why this exists -Approved: -``` -✅ Permission Protocol: Approved - View receipt → https://app.permissionprotocol.com/pp/deploy-requests/{id} -``` +AI agents can write code, open PRs, and trigger workflows — but they should not have authority to deploy on their own. ---- +Today: +- approvals are mutable +- logs are not proof +- systems trust state, not intent -## Configuration +Deploy Gate enforces: -| Input | Description | Default | -|-------|-------------|---------| -| `pp-api-key` | Your Permission Protocol API key | **Required** | -| `pp-base-url` | PP API base URL | `https://app.permissionprotocol.com` | -| `environment` | Environment bound to the receipt scope | `production` | -| `capability` | Capability bound to the receipt scope | `deploy:production` | -| `redeem` | Redeem receipt on verify (`false` for PR gate, `true` for deploy workflow) | `false` | -| `fail-on-missing` | Fail if no receipt | `true` | -| `fail-open-timeout` | Seconds to wait before PP API fail-open | `30` | -| `post-comment` | Post/update PR comment with receipt or approval link | `true` | +- Explicit human signer (Ed25519) +- Signature bound to exact action (commit, repo, environment) +- Single-use receipt (replay fails) +- Tamper-evident — mutation invalidates approval -
-Advanced configuration +It does not trust database state. Only signed receipts. -| Input | Description | Default | -|-------|-------------|---------| -| `pp-request-create-token` | Optional token to auto-create approval requests | `''` | -| `protected-paths` | Regex for risk assessment metadata (not gating) | `^(deploy/\|\.github/workflows/)` | +--- -### Risk Metadata Paths +## How it works -```yaml -- uses: permission-protocol/deploy-gate@v1 - with: - pp-api-key: ${{ secrets.PP_API_KEY }} - protected-paths: '^(src/critical/|infra/|\.env)' ``` - -### Outputs - -| Output | Description | -|--------|-------------| -| `approved` | `true` if approved, `false` otherwise | -| `receipt-id` | Receipt ID when a receipt is found | -| `decision` | Decision from receipt (`APPROVED`, `DENIED`, `PENDING`) | -| `error-code` | API error code when verification fails | -| `error-message` | API error message when verification fails | -| `request-id` | Deploy request ID (if created) | -| `approval-url` | URL to approve the deploy | - -```yaml -- uses: permission-protocol/deploy-gate@v1 - id: gate - with: - pp-api-key: ${{ secrets.PP_API_KEY }} - -- run: echo "Approval URL: ${{ steps.gate.outputs.approval-url }}" - if: failure() +PR opened + │ + ▼ +Deploy Gate checks for valid receipt + │ + ├── Receipt exists ───────────────► Merge allowed + │ + └── No receipt ───────────────────► Blocked + │ + ▼ + PR comment with approval link + │ + ▼ + Human approves + signs + │ + ▼ + Re-run CI → Merge allowed ``` -### GitHub Ruleset Pattern - -To avoid "merge loops" where approvals go stale when `main` advances, use a **two-ruleset pattern**: - -1. **Ruleset 1 (Permission Protocol):** Require `Permission Protocol` status check with **Strict mode: OFF**. -2. **Ruleset 2 (Build Protection):** Require your build/test checks with **Strict mode: ON**. - -[See full guide →](./INSTALL.md#%EF%B8%8F-critical-github-rulesets--strict-mode) - -
- --- ## Try it live (30 seconds) -No install needed. See the full flow on a real PR: - -1. **Open the demo PR** → [permission-protocol/pp-demo#23](https://github.com/permission-protocol/pp-demo/pull/23) -2. **Click "Authorize Deploy"** in the bot comment -3. **Sign in with GitHub** → approve → see the receipt +No install required: -That's the entire product. One blocked PR, one human signer, one receipt. - -Want to run it on your own repo? [Install guide →](./INSTALL.md) - ---- - -## Badge Usage - -

- deploy gate blocked badge - deploy gate approved badge -

- -```markdown -![deploy gate blocked](./assets/badge-blocked.svg) -![deploy gate approved](./assets/badge-approved.svg) -``` +1. Open demo PR + https://github.com/permission-protocol/pp-demo/pull/23 +2. Click Authorize Deploy +3. Sign → return → merge --- ## License -MIT. See [LICENSE](./LICENSE). - ---- - -

- - Get PP - -

- -

- Built by Permission Protocol · The Signer of Record for Autonomous Systems -

+MIT — see LICENSE