auth setup
Step-by-step provisioning of credentials for petrova --apply.
The user-facing summary is at /cli/auth/ — this
page is the operator runbook with troubleshooting.
Prerequisite
Section titled “Prerequisite”Decide: PAT or GitHub App?
- PAT if: solo dev, single user, short rotation cadence is fine.
- GitHub App if: multiple fleets, multiple users, want per-fleet audit log, want install/uninstall as the access toggle.
When in doubt, start with PAT. Migration to App later is straightforward (the CLI auto-detects which is set).
Path A: Fine-grained PAT
Section titled “Path A: Fine-grained PAT”Step 1 — generate
Section titled “Step 1 — generate”GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token.
Settings:
- Token name:
PETROVA-<env>(e.g.PETROVA-prod,PETROVA-test). - Expiration: maximum 90 days. Calendar a rotation reminder for 7 days prior.
- Resource owner: the org that owns governed repos
(e.g.
petrova-hq,kahn-hq). - Repository access: Only select repositories → list every
slug in
registry.yamlfor that owner. Avoid “All repositories”. - Permissions:
- Contents: Read and write
- Metadata: Read-only (auto-set)
- Pull requests: Read and write
- Administration: Read-only (only if using
request_merge_when_green— needed for branch-protection check)
Step 2 — store
Section titled “Step 2 — store”op item create --category=password \ --title="PETROVA_GITHUB_TOKEN" \ --vault=PETROVA \ password="<paste-token>"(Or your password manager of choice.)
Step 3 — export
Section titled “Step 3 — export”In your shell rc / .envrc:
export PETROVA_GITHUB_TOKEN="$(op read 'op://PETROVA/PETROVA_GITHUB_TOKEN/credential')"Step 4 — verify
Section titled “Step 4 — verify”echo "${PETROVA_GITHUB_TOKEN:0:4}…" # should print 'gith…' or similarpetrova open_decision petrova-hq --input /tmp/test-decision.json --apply --json | jq '.envelope.status'# Expected: "applied" or "skipped_idempotent"Troubleshooting
Section titled “Troubleshooting”AUTH_MISSING→ token not in environment. Re-export.403→ permissions too narrow. Check token scopes match the table above.404 Not Foundon a real repo → token’s repository access list doesn’t include this repo.401→ token expired or revoked. Generate a fresh one.
Path B: GitHub App
Section titled “Path B: GitHub App”Step 1 — register
Section titled “Step 1 — register”Org settings → Developer settings → GitHub Apps → New GitHub App.
Settings:
- Name:
PETROVA Control Plane. - Homepage URL:
https://petrova.devarno.cloud(orhttps://github.com/petrova-hq/petrova). - Webhook: disabled for now (re-enable when the deferred webhook receiver lands).
- Repository permissions:
- Contents: Read and write
- Metadata: Read-only
- Pull requests: Read and write
- Administration: Read-only
- Subscribe to events: push, pull_request (future use).
- Where can this GitHub App be installed? Only on this account.
Click Create.
Step 2 — generate private key
Section titled “Step 2 — generate private key”App’s settings → Private keys → Generate a private key.
Downloads as .pem.
mkdir -p ~/.petrovamv ~/Downloads/*.private-key.pem ~/.petrova/petrova-app.private-key.pemchmod 600 ~/.petrova/petrova-app.private-key.pemOr store the contents in 1Password:
op item create --category=secure-note \ --title="PETROVA App Private Key" \ --vault=PETROVA \ notes-plain="$(cat ~/.petrova/petrova-app.private-key.pem)"Step 3 — install on target repos
Section titled “Step 3 — install on target repos”App’s public page → Install → choose org → choose
Only select repositories → pick every slug in registry.yaml.
Note the Installation ID from the post-install URL:
https://github.com/settings/installations/<INSTALLATION_ID>.
Step 4 — export
Section titled “Step 4 — export”export PETROVA_APP_ID=12345 # from app's settings pageexport PETROVA_APP_PRIVATE_KEY_PATH=~/.petrova/petrova-app.private-key.pemexport PETROVA_APP_INSTALLATION_ID=67890 # from install URLStep 5 — verify
Section titled “Step 5 — verify”unset PETROVA_GITHUB_TOKEN # ensure App path is exercised, not PAT fallthroughpetrova open_decision petrova-hq --input /tmp/test-decision.json --apply --json | jq '.envelope.status'Troubleshooting
Section titled “Troubleshooting”AUTH_MISSING→ one of the three env vars unset. Check all three.Bad credentials→ private key path wrong, or key file permissions unreadable.cat $PETROVA_APP_PRIVATE_KEY_PATH | head -1should show-----BEGIN RSA PRIVATE KEY-----.403 Resource not accessible by integration→ app not installed on the target repo, or installation lacks the required permissions. Re-install or update install settings.401 Bad credentials→ installation ID wrong. Recheck.
Rotation
Section titled “Rotation”Calendar reminder 7 days before expiry. On rotation:
- Generate new token with same scopes.
- Update 1Password.
- Re-export in active shells.
- Revoke old token.
GitHub App key
Section titled “GitHub App key”Apps don’t expire, but rotate the private key annually:
- App settings → Private keys → Generate a new private key.
- Replace the
.pemon disk. - Re-export
PETROVA_APP_PRIVATE_KEY_PATHif path changed. - Revoke the old key.
Revoking access
Section titled “Revoking access”Revoke the token in GitHub. All --apply invocations using that
token immediately fail with 401.
GitHub App
Section titled “GitHub App”Either:
- Uninstall the app from the target repos (per-repo revocation), or
- Suspend the app entirely (org-wide revocation).
See also
Section titled “See also”/cli/auth/— user-facing summary./cli/configuration/— env var reference.