feat(agent-team): P3-live CI apply/verify hardening + ci_fetcher (gate-passed, provisioning-gated) #17

Merged
amoussa1229 merged 4 commits from feature/agent-team-p3-live into main 2026-06-18 19:53:27 +00:00
amoussa1229 commented 2026-06-18 19:52:07 +00:00 (Migrated from github.com)

P3-live — hardened CI apply/verify trust boundary (Decision 1: GitHub App token, ZERO AWS, no OIDC)

Brings the §3.3.2 CI apply/verify surface to gate-passed, ready-to-flip. Everything privileged stays inert until provisioning — the actual go-live flip is a provisioning action (the GitHub App + agent-apply environment + branch protection don't exist yet; flipping against a non-existent environment would be an unprotected hole).

What's in here

  • ci_fetcher.py — read-only, fail-closed CI-result fetcher (GitHub Actions run conclusion via a read-only PAT). Validates run_id/owner/repo/fetched_id, conclusion-allowlists, fails closed on any error. Data-fetcher only — ci_gate owns the verdict.
  • Workflow hardening (agent-team-apply-verify.yml): GitHub App token model (OIDC/id-token/AWS removed); task_id env-indirection (CWE-94); download-artifact run-id pinning; NUL-delimited post-build denied-path check; empty-hash fail-closed (fixed a real ''=='' pass bug); three trust-control denylists unified + drift-guard test.
  • Coordinator — opt-in gated_build_verify_wiring() (NOT in the default run-team.py path).
  • build(security-review) — prune .claude worktrees from the deterministic scanners + gitignore (unblocks main-tree pushes during parallel agent work).

Gates (both passed)

  • /sh-security-review (high-recall fan-out + proof-or-kill verifier) → PASS. The candidate high "SSRF via run_id" was refuted (run_id never populated from untrusted input; seam inert) but hardened anyway; 2 confirmed lows fixed.
  • GPT-4.1 cross-review (mandatory §3.3.2 cross-family) → first pass REQUEST CHANGES (3 BLOCK + 5 FIX), all fixed → re-review APPROVE (residual NITs only).
  • 884 tests pass; ruff clean.

⚠️ Provisioning prerequisites (flip happens THEN, not in this PR)

The app-token mint + draft-PR steps remain if: ${{ false }}; pull-requests: write + environment: agent-apply are commented. To go live (provisioning runbook):

  1. Create the GitHub App (pull-requests: write only), install on target repo(s); store AGENT_APPLY_APP_ID / AGENT_APPLY_APP_PRIVATE_KEY secrets.
  2. Create the agent-apply GitHub Environment with a required reviewer; add branch protection on target repos.
  3. Trim the build-test egress allowlist per target repo.
  4. Uncomment pull-requests: write + environment:; flip both if: ${{ false }} → always() && needs.guard.result=='success' && needs.build-test.result=='success'.
    Rollback: revert the uncomment/flip (single commit) → workflow returns fully inert; remove the GitHub App install + environment. Nothing is live to roll back until step 4.

Unblocks

Step 5 (Plane-1 fixer) reuses this exact GitHub App surface.

## P3-live — hardened CI apply/verify trust boundary (Decision 1: GitHub App token, ZERO AWS, no OIDC) Brings the §3.3.2 CI apply/verify surface to **gate-passed, ready-to-flip**. Everything privileged stays **inert** until provisioning — the actual go-live flip is a provisioning action (the GitHub App + `agent-apply` environment + branch protection don't exist yet; flipping against a non-existent environment would be an unprotected hole). ### What's in here - **`ci_fetcher.py`** — read-only, fail-closed CI-result fetcher (GitHub Actions run conclusion via a read-only PAT). Validates `run_id`/`owner`/`repo`/`fetched_id`, conclusion-allowlists, fails closed on any error. Data-fetcher only — `ci_gate` owns the verdict. - **Workflow hardening** (`agent-team-apply-verify.yml`): GitHub App token model (OIDC/`id-token`/AWS removed); `task_id` env-indirection (CWE-94); `download-artifact` run-id pinning; NUL-delimited post-build denied-path check; empty-hash fail-closed (fixed a real `''==''` pass bug); three trust-control denylists unified + drift-guard test. - **Coordinator** — opt-in `gated_build_verify_wiring()` (NOT in the default `run-team.py` path). - **`build(security-review)`** — prune `.claude` worktrees from the deterministic scanners + gitignore (unblocks main-tree pushes during parallel agent work). ### Gates (both passed) - **`/sh-security-review`** (high-recall fan-out + proof-or-kill verifier) → **PASS**. The candidate high "SSRF via run_id" was refuted (run_id never populated from untrusted input; seam inert) but hardened anyway; 2 confirmed lows fixed. - **GPT-4.1 cross-review** (mandatory §3.3.2 cross-family) → first pass REQUEST CHANGES (3 BLOCK + 5 FIX), all fixed → re-review **APPROVE** (residual NITs only). - 884 tests pass; ruff clean. ### ⚠️ Provisioning prerequisites (flip happens THEN, not in this PR) The app-token mint + draft-PR steps remain `if: ${{ false }}`; `pull-requests: write` + `environment: agent-apply` are commented. To go live (provisioning runbook): 1. Create the GitHub App (`pull-requests: write` only), install on target repo(s); store `AGENT_APPLY_APP_ID` / `AGENT_APPLY_APP_PRIVATE_KEY` secrets. 2. Create the `agent-apply` GitHub Environment with a **required reviewer**; add branch protection on target repos. 3. Trim the build-test egress allowlist per target repo. 4. Uncomment `pull-requests: write` + `environment:`; flip both `if: ${{ false }}` → `always() && needs.guard.result=='success' && needs.build-test.result=='success'`. **Rollback:** revert the uncomment/flip (single commit) → workflow returns fully inert; remove the GitHub App install + environment. Nothing is live to roll back until step 4. ### Unblocks Step 5 (Plane-1 fixer) reuses this exact GitHub App surface.
This repo is archived. You cannot comment on pull requests.
No description provided.