> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackra.figentra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 0167 — Workflow hardening, outside contributors and bot credentials

> Accepted · 2026-10-20

> [!NOTE]
>
> Amends [0012](/adr/0012-code-host-and-ci): the workflow rules below apply to every workflow in the
> repository.

## Context

GitHub Actions workflows run with broad default permissions, and a pull request from a fork can run them. The owner answered CI11–CI13 on 2026-10-20 (mem
L415–418). The bot credential that opens and merges pull requests also needs a home that is not a repository secret.

## Decision

1. **Least privilege (CI11).** Every workflow sets `permissions: {}` at the top and grants each job only what it needs. `zizmor` checks workflows. The
   setup action is `mise-action`.
2. **Bot credentials (CI12).** The bot App ID and private key move to Infisical `/ci`, read through OIDC. Until that move lands, they are release-environment
   secrets, never repository-wide secrets.
3. **Outside contributors (CI13).** Every run for an outside contributor waits for approval. `pull_request_target` never runs with a checkout of the pull request.

## Consequences

* A workflow that grants more than it needs fails `zizmor` review.
* A fork's pull request cannot read a secret or run with write access.
* The bot identity is the one the Quality Gate and `pr:merge` use (ADR 0119); a human's personal token is never used for merges.

## Enforcement

planned — `zizmor` in the gate for `.github/workflows/*`; the outside-contributor approval is a repository setting that the runbook records. The
`runbooks/secrets.mdx` page is updated with the bot-credential move (final pass).

## Alternatives

* Repository-wide bot secret: rejected by CI12.
* `pull_request_target` with a PR checkout: rejected by CI13.

## Supersedes and sources

Supersedes: none. Amends: [0012](/adr/0012-code-host-and-ci). Sources: owner answers CI11–CI13 (`stackra-decisions-2026-10-19.md` L415–418, 2026-10-20).
Closes gaps B25 and B26.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.