Unblock governance seeding (Phases 10–12): create GitHub App and wire GOVERNANCE_APP_ID / GOVERNANCE_APP_PRIVATE_KEY
What
seed-governance.yml (merged to main in #18, l9-github-defaults v3.1.0) cannot run. It authenticates as a GitHub App via actions/create-github-app-token, but neither credential exists anywhere on the repo or environment:
# .github/workflows/seed-governance.yml (lines 32, 39-40)
environment: governance-distribution # add required reviewers here
app-id: ${{ vars.GOVERNANCE_APP_ID }}
private-key: ${{ secrets.GOVERNANCE_APP_PRIVATE_KEY }}
Verified state at time of filing (2026-07-29):
| Item |
State |
governance-distribution environment |
EXISTS (created during v2.0.1 integration) |
| Environment variables / secrets |
NONE |
| Repo variables / secrets |
NONE |
| Environment required reviewers |
NONE |
| Everything else in the v3.1.0 playbook |
DONE (tags v3.1.0+v1, evaluate rulesets 19936069/19936070, secret-scanning alerts, labels, weekly posture report → #19) |
Why
Seeding is the distribution arm of the governance pack: it opens PRs on consuming repos with the pinned @v1 caller, CODEOWNERS.repo, and dependabot.yml. Current fleet coverage (posture report #19, 30 active repos): CODEOWNERS 30 percent, governance caller 3 percent, dependabot 53 percent. Until credentials exist, coverage cannot move.
A GitHub App (not a PAT) is required by design: scoped installation, short-lived tokens, revocable independently of any user account, and the seed workflow's approval gate (governance-distribution environment) assumes App auth.
Fix — steps for the executing agent (human confirmation needed at App creation)
- Create an org GitHub App at
https://github.com/organizations/Quantum-L9/settings/apps/new
- Name:
l9-governance-seeder (or similar)
- Permissions (minimum): Repository → Contents: Read and write, Pull requests: Read and write, Metadata: Read-only, Administration: Read-only
- Webhook: deactivate (not needed)
- Where: this account only
- Generate a private key (App settings → Private keys → Generate) — downloads a
.pem
- Install the App on the org: all repositories (or at minimum the repos to be seeded plus
.github)
- Store credentials on the
governance-distribution environment of Quantum-L9/.github:
gh api -X POST repos/Quantum-L9/.github/environments/governance-distribution/variables \
-f name=GOVERNANCE_APP_ID -f value=<APP_ID>
gh secret set GOVERNANCE_APP_PRIVATE_KEY \
--repo Quantum-L9/.github --env governance-distribution < app-private-key.pem
Note: vars.GOVERNANCE_APP_ID / secrets.GOVERNANCE_APP_PRIVATE_KEY resolve from the environment because the seeding job declares environment: governance-distribution. Repo-level storage also works but environment-level is preferred (keeps credentials behind the approval gate).
- Add a required reviewer to the environment (Settings → Environments → governance-distribution) so every seeding run pauses for human approval — this is the pack's intended control point.
- Dry-run first (playbook Phase 11):
gh workflow run seed-governance.yml --repo Quantum-L9/.github --ref main -f dry_run=true
Inspect the run summary: it must list target repos and intended files WITHOUT opening PRs.
- Live seed (Phase 12) only after dry-run output is reviewed:
gh workflow run seed-governance.yml --repo Quantum-L9/.github --ref main -f dry_run=false
Expected: one PR per target repo (advisory — merging them is each repo owner's call).
Acceptance criteria
Context / references
Priority
priority:P1 / scope:M — sole remaining blocker of the v3.1.0 rollout; all other playbook phases are complete.
Unblock governance seeding (Phases 10–12): create GitHub App and wire
GOVERNANCE_APP_ID/GOVERNANCE_APP_PRIVATE_KEYWhat
seed-governance.yml(merged tomainin #18, l9-github-defaults v3.1.0) cannot run. It authenticates as a GitHub App viaactions/create-github-app-token, but neither credential exists anywhere on the repo or environment:Verified state at time of filing (2026-07-29):
governance-distributionenvironmentv3.1.0+v1, evaluate rulesets 19936069/19936070, secret-scanning alerts, labels, weekly posture report → #19)Why
Seeding is the distribution arm of the governance pack: it opens PRs on consuming repos with the pinned
@v1caller,CODEOWNERS.repo, anddependabot.yml. Current fleet coverage (posture report #19, 30 active repos): CODEOWNERS 30 percent, governance caller 3 percent, dependabot 53 percent. Until credentials exist, coverage cannot move.A GitHub App (not a PAT) is required by design: scoped installation, short-lived tokens, revocable independently of any user account, and the seed workflow's approval gate (
governance-distributionenvironment) assumes App auth.Fix — steps for the executing agent (human confirmation needed at App creation)
https://github.com/organizations/Quantum-L9/settings/apps/newl9-governance-seeder(or similar).pem.github)governance-distributionenvironment ofQuantum-L9/.github:vars.GOVERNANCE_APP_ID/secrets.GOVERNANCE_APP_PRIVATE_KEYresolve from the environment because the seeding job declaresenvironment: governance-distribution. Repo-level storage also works but environment-level is preferred (keeps credentials behind the approval gate).Acceptance criteria
gh api repos/Quantum-L9/.github/environments/governance-distribution/variablesshowsGOVERNANCE_APP_IDgh api repos/Quantum-L9/.github/environments/governance-distribution/secretsshowsGOVERNANCE_APP_PRIVATE_KEYContext / references
docs/AGENT-DEPLOYMENT-RUNBOOK.mdPhases 10–12 (canonical procedure)docs/DISTRIBUTION.md(seeding semantics),docs/ADVISORY.md(nothing may block).githubitself; the seed PRs are the mechanism that reaches them.Priority
priority:P1/scope:M— sole remaining blocker of the v3.1.0 rollout; all other playbook phases are complete.