Context
GitHub Actions workflows receive a GITHUB_TOKEN by default with limited permissions: it only operates on the repo where it runs, it cannot create PRs if the org has that restriction active, and -- critically -- events it triggers do not execute other workflows (by design, to prevent infinite loops). This breaks many useful patterns: release bots that need to trigger downstream pipelines, cross-repo automation, or something as simple as /adr in a Discussion opening a PR that a validation workflow picks up.
The historical workaround has been a Personal Access Token (PAT) from some human with broad permissions. It works, but couples automation to that person, the tokens are long-lived, and scopes are granular only at the operation-type level, not per repo. Before we start building pipelines (package releases, ADR bootstrapping, cross-repo sync), it makes sense to establish a default policy so that individual decisions do not contradict each other.
Decision
When a pipeline or automation needs a token with permissions beyond the default GITHUB_TOKEN (for example: creating PRs, triggering downstream workflows, writing to other repos in the org, managing Discussions), the default approach is to issue the token from a GitHub App installed in the eigenoid org. Personal Access Tokens (PATs) are reserved for one-off, temporary cases.
Consequences
- Fine-grained permissions: each App explicitly declares what scopes it needs and on which repos; principle of least privilege.
- Short-lived tokens: the installation token expires in one hour; reduces impact if a key leaks.
- Clear identity: actions show up signed as the App (
eigenoid-bot[bot]), not as a person. Better auditability. - No coupling to a person: the token does not die if the owner rotates their PAT, leaves the org, or has their credentials rotated.
- PRs created by the App DO trigger downstream workflows (unlike those created with
GITHUB_TOKEN), eliminating a frequent gotcha. - Initial setup cost: the App must be created, a private key generated, the App installed on each repo, and
APP_ID+PRIVATE_KEYsecrets configured in each workflow. - One more layer to maintain: periodic rotation of the private key, managing who is the human owner of the App, monitoring which repos use it.
Alternatives considered
- PAT from a human user: simple to set up but couples automation to that person; if they leave or their permissions are rotated, the entire pipeline breaks. Tokens are long-lived by default.
- PAT from a dedicated bot account: improves ownership, but GitHub charges for the additional seat, PATs are still long-lived, and permissions remain coarse-grained (broad scopes).
- Always use
GITHUB_TOKEN: free and automatic, but permissions are limited to the repo where the workflow runs and, critically, events triggered by its actions do not execute other workflows (breaks chained automations). - Deploy keys or ephemeral tokens via OIDC to another provider: valid for specific integrations (e.g. cloud providers), not as a general mechanism within GitHub.
References
- About GitHub Apps — GitHub Docs
- Authenticating as a GitHub App installation
actions/create-github-app-token— official action to issue the token in a workflow.- GITHUB_TOKEN automatic permissions — what the default token can and cannot do.
- Comparing PATs vs GitHub Apps — official guide.