Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
deploy-production:
name: Deploy production
runs-on: ubuntu-latest
environment: production

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Because GitHub auto-creates the production environment with no protection rules on the first deployment when it doesn't already exist, the protection provided by environment: production silently disappears if the environment is missing or its reviewers are later removed. The repository risk here is mitigated by the human-only runbook and merge ordering, but the workflow itself never verifies that protection_rules is non-empty before running wrangler deploy. Consider adding a defense-in-depth guard step near the start of the job that queries repos/{owner}/{repo}/environments/production and fails the build unless a required_reviewers protection rule is present, so a misconfigured or auto-created phantom gate can't slip through to production.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/deploy.yml, line 21:

<comment>Because GitHub auto-creates the `production` environment with no protection rules on the first deployment when it doesn't already exist, the protection provided by `environment: production` silently disappears if the environment is missing or its reviewers are later removed. The repository risk here is mitigated by the human-only runbook and merge ordering, but the workflow itself never verifies that `protection_rules` is non-empty before running `wrangler deploy`. Consider adding a defense-in-depth guard step near the start of the job that queries `repos/{owner}/{repo}/environments/production` and fails the build unless a `required_reviewers` protection rule is present, so a misconfigured or auto-created phantom gate can't slip through to production.</comment>

<file context>
@@ -18,6 +18,7 @@ jobs:
   deploy-production:
     name: Deploy production
     runs-on: ubuntu-latest
+    environment: production
     steps:
       - name: Checkout code
</file context>

steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
102 changes: 102 additions & 0 deletions security/production-environment-runbook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Production deployment environment runbook

Status: prepared; human execution required

This runbook creates the GitHub `production` environment that gates
`.github/workflows/deploy.yml`. An agent must not execute the settings change:
the shared agent identity is `willwashburn`, and an identity that can create,
edit, or delete its own gate is not constrained by that gate.

The environment needs two independent controls. Required reviewers and
prevent-self-review determine **who** may approve a deployment. A custom
deployment branch policy determines **what** may deploy by restricting the
environment to `main`. Neither control substitutes for the other.

## Required human decision

Chief must confirm the required reviewer before this runbook is executed.
CMO recommends `khaliqgant` (GitHub user ID `1724137`), the only known human
organization identity that is neither `willwashburn` nor a member of the
agent-oriented `claws` team. Do not substitute `willwashburn`; agents use that
credential and could approve their own deployment.

## Configure with the GitHub UI

1. As a human repository administrator, open **Settings → Environments** for
`AgentWorkforce/agentrelay.com`.
2. Create an environment named exactly `production`.
3. Attempt to enable **Required reviewers** and add the chief-confirmed human
reviewer. Availability of required environment reviewers has not been
established for this free organization plan. If GitHub does not offer the
control or refuses the change, stop and report that result; do not continue
as though the reviewer gate exists.
4. Enable **Prevent self-review**.
5. Under **Deployment branches and tags**, select **Selected branches and
tags**, add a custom deployment branch rule for exactly `main`, and do not
enable the branch-protection-based option. This repository has no branch
protection rules, so that option would not constrain the deployable ref.
6. Save the protection rules.

## Configure with the GitHub API

After chief confirms `khaliqgant`, a human repository administrator may run
the following. The first request is also the availability test for required
environment reviewers on this organization plan. If GitHub refuses it, stop
and report the response; do not create only the branch policy and treat the
environment as complete.

```bash
gh api --method PUT \
repos/AgentWorkforce/agentrelay.com/environments/production \
--input - <<'JSON'
{
"wait_timer": 0,
"prevent_self_review": true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The runbook's API example and UI steps don't disable administrator bypass. According to GitHub's deployment protection rules documentation, administrators can bypass protection rules and force deployments by default, and this is a separate setting from prevent_self_review. Since the shared willwashburn identity has repository-administrator access, it could still bypass the required human reviewer gate unless can_admins_bypass is explicitly set to false. Add that setting to the API payload, add a UI step to disable admin bypass, and include the value in the required read-back check.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At security/production-environment-runbook.md, line 37:

<comment>The runbook's API example and UI steps don't disable administrator bypass. According to GitHub's deployment protection rules documentation, administrators can bypass protection rules and force deployments by default, and this is a separate setting from prevent_self_review. Since the shared willwashburn identity has repository-administrator access, it could still bypass the required human reviewer gate unless can_admins_bypass is explicitly set to false. Add that setting to the API payload, add a UI step to disable admin bypass, and include the value in the required read-back check.</comment>

<file context>
@@ -0,0 +1,68 @@
+  --input - <<'JSON'
+{
+  "wait_timer": 0,
+  "prevent_self_review": true,
+  "reviewers": [
+    {
</file context>

"reviewers": [
Comment on lines +53 to +55

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Disable administrator bypass for the production gate

Because the shared willwashburn identity has repository-administrator access, omitting can_admins_bypass leaves GitHub's administrator-bypass behavior enabled by default. That identity can therefore bypass a waiting deployment without the required human reviewer, and prevent_self_review does not prevent this separate admin-bypass path. Set can_admins_bypass to false, instruct UI users to disable administrator bypass, and include that value in the required read-back.

Useful? React with 👍 / 👎.

{
"type": "User",
"id": 1724137
}
],
"deployment_branch_policy": {
"protected_branches": false,
"custom_branch_policies": true
}
}
JSON

gh api --method POST \
repos/AgentWorkforce/agentrelay.com/environments/production/deployment-branch-policies \
-f name=main
```

## Required read-back

The resident `agentrelay-com` agent must independently run this read-only check
after the human reports completion:

```bash
gh api repos/AgentWorkforce/agentrelay.com/environments/production \
--jq '{name, protection_rules}'

gh api \
repos/AgentWorkforce/agentrelay.com/environments/production/deployment-branch-policies \
--jq '{total_count, branches: [.branch_policies[].name]}'
```

The workflow PR must not merge unless all of these are true:

- the response names `production`;
- `protection_rules` is non-empty;
- a `required_reviewers` rule names the chief-confirmed human reviewer; and
- the deployment-branch-policy response contains exactly one entry, `main`;
- `.github/workflows/deploy.yml` references `environment: production` on the
`deploy-production` job.

The reviewer rule answers who can approve. The custom branch policy answers
what can deploy. Keeping `workflow_dispatch` is safe only when the environment
rejects every triggering ref except `main`.

Merging the workflow reference before the protection exists would allow GitHub
to auto-create an unprotected environment during a production deploy. That is
a phantom gate and is explicitly prohibited.
Loading