Skip to content

feat(ipr): cross-repo callable workflow + GitHub App support#3134

Merged
bokelley merged 2 commits intomainfrom
bokelley/ipr-cross-repo
Apr 25, 2026
Merged

feat(ipr): cross-repo callable workflow + GitHub App support#3134
bokelley merged 2 commits intomainfrom
bokelley/ipr-cross-repo

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Summary

Phase 1 of Batch C: enable AAO repositories beyond adcp to write back to the central IPR signature ledger via a GitHub App installation token. After this lands and the App is verified working in adcp itself, four follow-up PRs (one per downstream repo) add the tiny caller workflows.

What's in this PR

  1. LEDGER_DIR env var in scripts/ipr/check-and-record.mjs so the script can run against a checked-out clone of the central ledger rather than cwd. Defaults to cwd — adcp's own workflow keeps working unchanged.
  2. Reusable callable workflow at .github/workflows/ipr-check-callable.yml. Downstream repos invoke it via:
    uses: adcontextprotocol/adcp/.github/workflows/ipr-check-callable.yml@main
    secrets:
      IPR_APP_ID: ${{ secrets.IPR_APP_ID }}
      IPR_APP_PRIVATE_KEY: ${{ secrets.IPR_APP_PRIVATE_KEY }}
    The callable mints the App token, checks adcp out into .ipr-ledger/, runs the script. PR comments + status check stay on the event repo via its default GITHUB_TOKEN.
  3. Concurrency alignment: adcp's existing workflow now uses the same adcp-ipr-signature-write group as the callable, so signatures from any repo serialize against each other.
  4. Setup docs at governance/ipr-bot-setup.md — App configuration, secret rotation, revocation procedure, per-repo adoption checklist.

Pre-requisites (already done by @bokelley)

  • AAO IPR Bot GitHub App created in adcontextprotocol org
  • App installed on the 5 AAO repos with Contents:RW + Pull-requests:W + Statuses:W + Metadata:R
  • IPR_APP_ID and IPR_APP_PRIVATE_KEY stored as org-level secrets, scoped to those repos

Test plan

  • node --check scripts/ipr/check-and-record.mjs — script parses
  • Smoke test the script with a no-op event payload — runs and exits clean
  • After merge: open a test PR in adcp from a non-signed account; verify ipr-check goes through the existing path (LEDGER_DIR defaults work; no behavior change)
  • After merge: roll out the caller workflow to ONE downstream repo first (suggest adcp-client) and verify a real PR-level signature lands in adcp@main:signatures/ipr-signatures.json
  • Then roll to the remaining three

Follow-ups still queued

  • Four small per-repo PRs adding the caller workflow to adcp-client, adcp-client-python, adcp-go, creative-agent. I'll open these as draft PRs once this PR is reviewed so the test order is controlled.
  • Branch protection on main requiring IPR Policy / Signature (separate ops PR — needs to be coordinated with the cross-repo rollout so we don't lock out our own bot before it works).
  • Dismiss CodeQL alerts 1306/1307 (UI-only, separate from this PR).

🤖 Generated with Claude Code

bokelley and others added 2 commits April 25, 2026 09:42
Adds LEDGER_DIR env var to scripts/ipr/check-and-record.mjs so the
script can read/write signatures and run git ops in a directory other
than cwd. Defaults to cwd, so adcp's existing workflow stays unchanged.

Adds .github/workflows/ipr-check-callable.yml — a reusable workflow
that downstream AAO repos invoke from their own ipr-agreement.yml.
The callable mints a GitHub App installation token scoped to adcp,
checks the central ledger out into .ipr-ledger/, and runs the same
script against it. PR comments and the IPR Policy / Signature commit
status both stay on the caller repo via its default GITHUB_TOKEN; the
git push back to adcp uses the App token.

Aligns adcp's existing concurrency group to adcp-ipr-signature-write
(was ipr-signature-write) so signatures from any AAO repo serialize
against each other on the shared JSON file.

governance/ipr-bot-setup.md documents the GitHub App configuration,
permissions, install scope, secret rotation, revocation, and the
per-repo adoption checklist. Per-repo caller workflows for
adcp-client / adcp-client-python / adcp-go / creative-agent ship as
separate PRs once this lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code review:
- Delete the misleading "cross-repo concurrency" claim from comments
  and docs. GitHub Actions concurrency is scoped per-repo, so the
  shared group name does NOT serialize between adcp's local workflow
  and the callable in downstream repos. Real serialization comes from
  the rebase-retry loop in commitSignaturesChange.
- Bump rebase-retry attempts from 3 to 5 for higher contention from
  up to 5 sibling repos pushing to the same JSON file.

Security review:
- Add explicit "do not add a caller checkout" guard comment in the
  callable workflow. PR-head code must never run in this job; the App
  token + caller's GITHUB_TOKEN are both in env.
- Validate LEDGER_DIR's `origin` remote URL matches
  adcontextprotocol/adcp before any git push. Removes a class of
  "future workflow edit changes which checkout backs LEDGER_DIR"
  footguns.
- Fix governance/ipr-bot-setup.md: org secrets with selected-repository
  visibility require explicitly adding the new repo, not "default".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant