Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions .github/workflows/github-settings-drift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,28 @@ on:
- ".github/workflows/github-settings-drift.yml"

permissions:
# Rulesets, branch protection, security_and_analysis,
# secrets counts, deploy keys, webhooks require
# `administration: read`. `actions: read` covers workflow
# reads + Actions variables + environments. `contents: read`
# is the baseline for `actions/checkout`.
# `actions: read` covers workflow reads + Actions variables +
# environments. `contents: read` is the baseline for
# `actions/checkout`.
#
# NOTE (B-0087, 2026-05-03): the previous `administration: read`
# entry was an invalid permission scope — actionlint and GitHub
# both reject it. `administration` is NOT a GITHUB_TOKEN scope;
# admin-level reads (rulesets, branch protection,
# security_and_analysis, secrets counts, deploy keys, webhooks,
# autolinks, automated-security-fixes, private-vulnerability-
# reporting) require a separately configured PAT or GitHub App
# token.
#
# Removing the line lets the workflow START successfully (it had
# been workflow-startup-failing on every push/cron for the entire
# history of LFG main); the drift detector script will return
# 403 on admin-only endpoints when run under GITHUB_TOKEN, but
# that is a SEPARATE issue (option B/C in B-0087) requiring
# maintainer action to configure DRIFT_DETECTOR_PAT secret. This
# commit fixes only the startup-failure half.
contents: read
actions: read
administration: read

concurrency:
group: github-settings-drift
Expand Down
2 changes: 1 addition & 1 deletion docs/BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ are closed (status: closed in frontmatter)._
- [ ] **[B-0066](backlog/P1/B-0066-memory-md-marker-vs-index-harness-verify-q1-automemory-aaron-2026-04-28.md)** MEMORY.md marker-vs-index — verify harness contract + Q1 AutoDream/AutoMemory compatibility, then migrate (Aaron 2026-04-28)
- [ ] **[B-0067](backlog/P1/B-0067-cadenced-git-hotspot-detection-aaron-2026-04-28.md)** Cadenced git-hotspot detection — find files-touched-by-many-PRs and migrate to per-row format (Aaron 2026-04-28)
- [ ] **[B-0083](backlog/P1/B-0083-atari-2600-rom-canonical-naming-tosec-goodtools-tooling-aaron-2026-04-28.md)** Atari 2600 ROM canonical-naming + safe-vs-unsafe folder split + TOSEC/Good-Tools-style hash-lookup tooling
- [ ] **[B-0087](backlog/P1/B-0087-github-settings-drift-workflow-broken-invalid-permission-administration-otto-2026-04-28.md)** github-settings-drift.yml has been broken since PR #45 — declares invalid GHA permission `administration: read`
- [ ] **[B-0087](backlog/P1/B-0087-github-settings-drift-workflow-broken-invalid-permission-administration-otto-2026-04-28.md)** github-settings-drift.yml broken since PR #45 — option A landed (invalid permission removed); options B/C remain maintainer-gated
- [ ] **[B-0110](backlog/P1/B-0110-acehack-mirror-protocol-drift-2026-04-30.md)** AceHack mirror-refresh protocol drift — Path 2 chosen, doctrine update landing in same PR (2026-04-30)
- [x] **[B-0125](backlog/P1/B-0125-skip-fsharp-analyze-on-docs-only-prs-2026-05-01.md)** Skip F#/Analyze (csharp) on docs-only PRs without tripping `code_quality severity:all`
- [ ] **[B-0126](backlog/P1/B-0126-port-meta-learning-4-layer-pattern-from-stcrm-aaron-2026-05-01.md)** Port the 4-layer meta-learning pattern from a sibling repo to Zeta
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
---
id: B-0087
priority: P1
status: open
title: github-settings-drift.yml has been broken since PR #45 — declares invalid GHA permission `administration: read`
status: partial
title: github-settings-drift.yml broken since PR #45 — option A landed (invalid permission removed); options B/C remain maintainer-gated
tier: factory-tooling
effort: S
ask: autonomous-loop tick discovery 2026-04-28T20:05Z (workflow-null-result audit class first concrete catch)
created: 2026-04-28
last_updated: 2026-05-02
last_updated: 2026-05-03
depends_on: []
composes_with:
- B-0085
tags: [otto-2026-04-28, github-actions, workflow-startup-failure, invalid-permission, drift-detector-broken, factory-hygiene]
tags: [otto-2026-04-28, github-actions, workflow-startup-failure, invalid-permission, drift-detector-broken, factory-hygiene, option-a-landed]
---

# B-0087 — github-settings-drift.yml broken since PR #45
Expand Down Expand Up @@ -130,14 +130,20 @@ for security audits.

## Acceptance criteria

- [ ] Maintainer picks A / B / C (or alternative path)
- [ ] github-settings-drift.yml passes `actionlint` cleanly
(no unknown permission scope warnings)
- [ ] Workflow runs to completion (success OR drift-detected
exit code 1, NOT workflow-startup failure)
- [ ] Cadenced cron run on next Monday 14:17 UTC confirms
fix (or shows real drift findings if option A drops some
endpoints)
- [x] Option A landed (2026-05-03): invalid `administration: read` permission removed; workflow startup-failure resolved.
- [x] github-settings-drift.yml passes `actionlint` cleanly (no unknown permission scope warnings) — verified via this PR.
- [x] Workflow no longer fails at workflow-startup ("workflow file issue"). It now reaches the drift-check step. Under GITHUB_TOKEN the snapshot script will likely exit 2 (tooling/input failure) on the first admin-only endpoint returning 403 — that's expected post-option-A behavior, NOT a regression. Exit codes 0 (no-drift) and 1 (drift-detected) are only achievable once option B (PAT) or C (GitHub App) is in place.
- [ ] Cadenced cron run on next Monday 14:17 UTC confirms fix at LFG-canonical level (reaches the script step instead of failing at startup; exit-2 expected until option B/C).
- [ ] **(Maintainer-gated, options B/C):** drift detector calls admin-only endpoints (`/automated-security-fixes`, `/private-vulnerability-reporting`, `/autolinks`, etc.) which return 403 under GITHUB_TOKEN; full fidelity requires `DRIFT_DETECTOR_PAT` secret (option B) or GitHub App (option C). Tracked as separate maintainer-action follow-on.

## What option A did NOT fix

The drift detector script (`tools/hygiene/check-github-settings-drift.sh`) calls a mix of public + admin-scope GitHub API endpoints. Under GITHUB_TOKEN (post-option-A), the public endpoints return correct data; the admin-scope endpoints (rulesets at the org level, autolinks, security configs) return 403. The drift detector either:

1. Fails on the first admin-scope endpoint (if it doesn't tolerate 403), OR
2. Reports phantom drift on the admin-scope fields (if it tolerates 403 by emitting null).

Either way, partial drift coverage. Maintainer-action (configure PAT secret) is the path to full coverage. This row stays open in `partial` status to track the residual maintainer-gated work.

## Operational note

Expand Down
Loading