Skip to content
Merged
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
26 changes: 15 additions & 11 deletions .github/workflows/attest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ name: attest
# stage 1 pre-fetch the package with scripts disabled (network on, no third-party code runs)
# stage 2 capture the declared surface inside a network-less, non-root, read-only sandbox
# stage 3 Sigstore-sign the lock on the runner, bound to the package coordinate (v2 statement)
# then open ONE pull request containing only new paths. See docs/SANDBOX.md.
# then land ONE commit containing only new paths on main, behind the append-only gate.
# See docs/SANDBOX.md.
#
# The signing identity is this workflow at main:
# https://github.com/DataScience-EngineeringExperts/mcp-warden-locks/.github/workflows/attest.yml@refs/heads/main
Expand Down Expand Up @@ -100,7 +101,6 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
checks: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -112,7 +112,12 @@ jobs:
path: incoming
merge-multiple: true

- name: Open one PR with only new paths, then report + arm the gate
# The enterprise setting forbids GITHUB_TOKEN from opening pull requests, so the
# attester lands its commit directly — but ONLY after the same append-only gate a
# human PR gets has passed on that exact commit and been reported as the required
# `append-only` check. Branch protection (required check + enforce_admins, no
# force-push, no deletion) is what admits the fast-forward; nothing else can.
- name: Land new lock paths on main behind the append-only gate
env:
GH_TOKEN: ${{ github.token }}
run: |
Expand All @@ -123,7 +128,7 @@ jobs:
(cd incoming && find . -type f | sed 's#^\./##') | while read -r f; do
if [ -e "locks/$f" ]; then echo "skip existing locks/$f"; else mkdir -p "$(dirname "locks/$f")"; cp "incoming/$f" "locks/$f"; fi
done
if git diff --quiet && [ -z "$(git ls-files --others --exclude-standard locks)" ]; then echo "nothing new"; exit 0; fi
if [ -z "$(git ls-files --others --exclude-standard locks)" ]; then echo "nothing new"; exit 0; fi
day=$(date -u +%Y-%m-%d); run="$GITHUB_RUN_ID"
branch="attest/$day-$run"
count=$(git ls-files --others --exclude-standard locks | grep -c '\.lock$' || true)
Expand All @@ -132,15 +137,14 @@ jobs:
git checkout -b "$branch"
git add locks
git commit -q -m "attest: $day ($count new locks)" -m "attester=$ATTESTER_ID warden=$WARDEN_REF run=$run"
git push -u origin "$branch"
head=$(git rev-parse HEAD)
# The same gate the pull_request workflow runs — reported as a check-run because
# token-caused events do not start workflows. Fails closed: a violation aborts here.
# Gate first, fail closed: a violation stops here and nothing is pushed anywhere.
bash tools/append_only_check.sh origin/main "$head"
pr=$(gh pr create --base main --head "$branch" --title "attest: $day ($count new locks)" \
--body "Nightly attestation by \`$ATTESTER_ID\` — $count new lock(s), mcp-warden \`$WARDEN_REF\`, run $run. Only new paths; see docs/SANDBOX.md. Consensus attests observation, not safety.")
git push -u origin "$branch"
gh api "repos/$GITHUB_REPOSITORY/check-runs" -f name=append-only -f head_sha="$head" \
-f status=completed -f conclusion=success \
-f 'output[title]=append-only OK' -f "output[summary]=$count new lock path(s); no modifications or deletions under locks/ or attesters.json." >/dev/null
gh pr merge --squash --auto "$pr"
echo "opened $pr"
# Fast-forward main. Branch protection admits this only because `append-only` is green on $head.
gh api -X PATCH "repos/$GITHUB_REPOSITORY/git/refs/heads/main" -f sha="$head" -F force=false >/dev/null
git push origin --delete "$branch"
echo "landed $count new lock(s) on main at $head"
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ Signature verification needs network to Sigstore's trust root on first use.

`.github/workflows/attest.yml` runs nightly: for each target in `targets.yaml` with no lock
yet — pre-fetch with install scripts disabled → capture inside a **network-less, non-root,
read-only, capability-dropped** container → sign on the runner with ambient OIDC → one PR
with only new paths, merged automatically once the `append-only` gate passes. The full
read-only, capability-dropped** container → sign on the runner with ambient OIDC → one commit
with only new paths, landed on `main` only after the `append-only` gate has passed on that
exact commit (the org forbids Actions from opening PRs, so the attester fast-forwards `main`
behind the same required check every human PR must pass). The full
contract, and what it does *not* defend against, is in [`docs/SANDBOX.md`](docs/SANDBOX.md).

Targets are pinned exact versions from the official MCP servers and widely used third-party
Expand Down