Skip to content

fix(repo-standard): one reusable workflow = one authority ceiling (#55) - #57

Merged
bdelanghe merged 1 commit into
mainfrom
claude/repo-standard-authority-ceilings
Jul 8, 2026
Merged

fix(repo-standard): one reusable workflow = one authority ceiling (#55)#57
bdelanghe merged 1 commit into
mainfrom
claude/repo-standard-authority-ceilings

Conversation

@bdelanghe

Copy link
Copy Markdown
Contributor

Problem

repo-standard.yml @ #54 (60745f9b) raised its permission floor above contents: read: the sbom job declares contents: write and scorecard declares actions: read. GitHub validates a called reusable workflow's permission requests as the union of all its jobs, at load time, before any if: — so every caller, even a read-only spell/security PR run, had to grant the superset or get a zero-jobs startup_failure. That's the #55 root cause (confirmed: org allowed_actions: "all", so it was never the Actions allowlist), and why conformance#19 is blocked.

Fix — one reusable workflow = one authority ceiling

Workflow Ceiling Jobs
repo-standard.yml contents: read osv, dependency-review, spell, test, descriptor
repo-scorecard.yml contents: read + actions: read scorecard
repo-release.yml contents: write sbom (+ upload-release-assets input)

Because the caller grant is validated as the union of the called workflow's jobs, each distinct ceiling must be its own file — otherwise a scorecard-only caller (scorecard was default: true, i.e. ~every repo) would be forced to grant contents: write. Callers now opt into the elevated ceilings with dedicated, event-gated jobs, so a PR run never instantiates write authority.

Regression guard (closes #56)

repo-standard-selftest.yml calls each reusable workflow at its intended ceiling. GitHub validates the permission union at load time, so a future revision that raises a floor fails here, pre-merge, instead of in every downstream repo — the self-test this repo lacked (which is how #54 shipped green). It also doubles as the reference caller template.

Caller migration (separate PR)

Callers that used scorecard: true / sbom: true inputs move those to dedicated jobs calling repo-scorecard.yml / repo-release.yml. Tracked for conformance in conformance#19; other repos on the old pin are unaffected until they bump.

PR checklist

  1. Independent PR.github reusable-workflow split only; caller adoption (conformance#19) is separate
  2. Changed codepaths verified — self-test caller exercises all three ceilings in CI (this PR's own run)
  3. Root cause identified — load-time permission union above the contents: read floor (evidence in repo-standard.yml @ #54 fails caller startup: scorecard/sbom actions not in the org Actions allowlist #55)
  4. No duplication — jobs moved, not copied; logic unchanged
  5. No unrelated changes — no behavior changes to the jobs themselves

Fixes #55. Closes #56. Unblocks conformance#19.

🤖 Generated with Claude Code

repo-standard.yml @ #54 raised its permission floor above `contents: read`
(sbom needs `contents: write`, scorecard needs `actions: read`). GitHub
validates a called reusable workflow's permission requests as the UNION of
all its jobs, at load time, before any `if:` — so every caller, even a
read-only spell/security PR run, had to grant the superset or hit a
zero-jobs `startup_failure`. That is why #54 could not start and why
conformance#19 is blocked.

Restore one reusable workflow = one authority ceiling:
- repo-standard.yml  — stays `contents: read` (osv, dependency-review,
  spell, test, descriptor); drops the scorecard/sbom jobs + inputs
- repo-scorecard.yml — `contents: read` + `actions: read` (scorecard)
- repo-release.yml   — `contents: write` (sbom); adds an
  `upload-release-assets` input so callers can take the SBOM artifact
  without a release upload

Callers opt into the elevated ceilings with dedicated, event-gated jobs, so
a PR run never instantiates write authority.

Add repo-standard-selftest.yml: calls each reusable workflow at its intended
ceiling. GitHub validates the permission union at load time, so a future
revision that raises a floor fails here, pre-merge, instead of in every
downstream repo — the self-test guard #55/#56 identified as missing. It also
doubles as the reference caller template.

Fixes #55. Closes #56. Unblocks conformance#19.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@bdelanghe
bdelanghe marked this pull request as ready for review July 8, 2026 23:26
@bdelanghe
bdelanghe merged commit 53efbd8 into main Jul 8, 2026
18 checks passed
@bounded-systems-front-desk bounded-systems-front-desk Bot moved this from Todo to Done in Front Desk Jul 8, 2026
bdelanghe added a commit that referenced this pull request Jul 8, 2026
The flake repos (door-concierge/keeper/net/peercred/scout, claude-box, facilities)
each carry a near-identical flakehub-publish.yml — checkout → nix-installer →
flakehub-push. Factor it into one reusable workflow so callers just configure
rolling/visibility (derive, not copy).

Authority ceiling `id-token: write` (FlakeHub OIDC) + `contents: read` — a ceiling
distinct from repo-standard.yml's, so per one-workflow-one-ceiling (#57) it is its
own file. Pins bumped to the org standard where they'd drifted (checkout v4→v7;
nix-installer moving `# main` → a fixed SHA).

Retires 2 outer-set actions (nix-installer-action, flakehub-push) from ~7 repos'
direct usage, folding them into the canonical set. Caller migration is a follow-up
(per-repo thin caller); this PR only adds the reusable workflow.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

1 participant