Background
Temper currently manages repository-level settings: branch protection, rulesets, merge strategy, labels, dependabot config. It does not manage org-level GitHub settings, so a chunk of organisation hardening still has to be clicked through in the GitHub UI by hand.
Two specific org-level settings worth bringing under temper's control:
1. Fork-PR approval policy
- Setting: Org Settings → Actions → General → "Fork pull request workflows from outside collaborators"
- Recommended value:
Require approval for all outside collaborators
- Why: an outside collaborator opening a fork PR can otherwise trigger workflows that read repo secrets / write to the cache. The default in newer orgs is already this, but the setting drifts (especially when a sub-org is migrated from a personal account) and there's no way to verify it short of clicking through.
- REST API:
GET/PATCH /orgs/{org}/actions/permissions/workflow covers a related toggle (default_workflow_permissions); the fork-PR-approval policy specifically is GET/PATCH /orgs/{org}/actions/permissions with enabled_repositories and the new default_workflow_permissions shape. The fork-PR approval setting itself is exposed via GET/PATCH /orgs/{org}/actions/permissions/fork-pr-workflows-from-outside-collaborators (recently added — verify the path against the docs at implementation time).
2. Allowed actions allowlist
- Setting: Org Settings → Actions → General → "Allow actions and reusable workflows"
- Recommended value:
Allow [pulseengine, actions, github] actions and reusable workflows plus an explicit allowlist of vetted third parties (e.g. Swatinem/rust-cache@*, bazel-contrib/setup-bazel@*, anchore/sbom-action@*, actions/attest-build-provenance@*).
- Why: without an allowlist, any new workflow file (whether on main, on a PR, or in a fork) can pull a fresh action from an arbitrary publisher and run it inside the repo's runner. Combined with the cache poisoning surface, this is one of the easier supply-chain footguns in GitHub Actions today.
- REST API:
GET/PATCH /orgs/{org}/actions/permissions/selected-actions returns/accepts the patterns_allowed array.
Proposed config shape
# config.yml
org_actions:
fork_pr_approval:
# 'all' | 'collaborators' | 'first_time_contributors' | 'never'
require_approval_for: all
allowed_actions:
# If null, allow all (the github default). If a list, becomes the
# exclusive allowlist plus the org's own actions plus github + actions.
patterns_allowed:
- actions/*
- github/*
- pulseengine/*
- Swatinem/rust-cache@*
- bazel-contrib/setup-bazel@*
- anchore/sbom-action@*
- actions/attest-build-provenance@*
Implementation notes
- These are org-level API calls — only the org admin's installation token can apply them. Verify the bot's app installation has
organization_administration: write (it currently doesn't; needs a permission update + re-consent during install).
- Apply in the same scheduled sweep that already does branch-protection drift correction. Compare current → desired, PATCH only on diff, log every change with a clear "applied org policy" log line.
- Idempotency: read-back-and-assert after PATCH (same pattern temper uses for repository-level settings).
- A
chatops:check-org-policy issue form would be useful to dry-run the diff without applying.
Out of scope for this issue
- Per-repo Actions permission overrides (
repos/{owner}/{repo}/actions/permissions) — a sibling feature, would track separately.
- The existing repo-level fork-PR approval (some repos have a per-repo override of the org default) — defer until the org-level path is solid.
Why now
Came up while applying smithy required-checks defaults to temper's config.yml (PR #57). The branch-protection floor is now config-managed; the org-level Actions policy is still drift-prone UI-only. Closing that gap means a single source of truth for "what the org's CI can do".
🤖 Issue authored with Claude Code
Background
Temper currently manages repository-level settings: branch protection, rulesets, merge strategy, labels, dependabot config. It does not manage org-level GitHub settings, so a chunk of organisation hardening still has to be clicked through in the GitHub UI by hand.
Two specific org-level settings worth bringing under temper's control:
1. Fork-PR approval policy
Require approval for all outside collaboratorsGET/PATCH /orgs/{org}/actions/permissions/workflowcovers a related toggle (default_workflow_permissions); the fork-PR-approval policy specifically isGET/PATCH /orgs/{org}/actions/permissionswithenabled_repositoriesand the newdefault_workflow_permissionsshape. The fork-PR approval setting itself is exposed viaGET/PATCH /orgs/{org}/actions/permissions/fork-pr-workflows-from-outside-collaborators(recently added — verify the path against the docs at implementation time).2. Allowed actions allowlist
Allow [pulseengine, actions, github] actions and reusable workflowsplus an explicit allowlist of vetted third parties (e.g.Swatinem/rust-cache@*,bazel-contrib/setup-bazel@*,anchore/sbom-action@*,actions/attest-build-provenance@*).GET/PATCH /orgs/{org}/actions/permissions/selected-actionsreturns/accepts thepatterns_allowedarray.Proposed config shape
Implementation notes
organization_administration: write(it currently doesn't; needs a permission update + re-consent during install).chatops:check-org-policyissue form would be useful to dry-run the diff without applying.Out of scope for this issue
repos/{owner}/{repo}/actions/permissions) — a sibling feature, would track separately.Why now
Came up while applying smithy required-checks defaults to temper's
config.yml(PR #57). The branch-protection floor is now config-managed; the org-level Actions policy is still drift-prone UI-only. Closing that gap means a single source of truth for "what the org's CI can do".🤖 Issue authored with Claude Code