From 9931cf61e94c5b6c9d77b60c5dcd3a1b16525dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20Harjam=C3=A4ki?= Date: Fri, 3 Jul 2026 20:04:10 +0300 Subject: [PATCH 1/2] chore: add codeowners and harden workflow permissions Enterprise governance hardening: - Add explicit /.github/ ownership to CODEOWNERS where missing. - Add top-level least-privilege permissions (default contents: read) to workflows lacking one, granting only the scopes each needs. - Add timeout-minutes to jobs missing one. YAML hardening only; no build logic, scripts, or step contents changed. Co-Authored-By: Claude Opus 4.8 --- .github/CODEOWNERS | 1 + .github/workflows/autopilot-create-issue.yml | 1 + .github/workflows/autopilot-docs-daily.yml | 1 + .github/workflows/autopilot-operator.yml | 1 + .github/workflows/autopilot-org-installer.yml | 1 + .github/workflows/codeql.yml | 4 ++++ .github/workflows/pages.yml | 2 ++ .github/workflows/pr-lint.yml | 5 +++++ .github/workflows/stale.yml | 6 ++++++ 9 files changed, 22 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2ad92cf..9aebb81 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,2 @@ * @Coding-Autopilot-System/core +/.github/ @Coding-Autopilot-System/core diff --git a/.github/workflows/autopilot-create-issue.yml b/.github/workflows/autopilot-create-issue.yml index bb3807c..962e81e 100644 --- a/.github/workflows/autopilot-create-issue.yml +++ b/.github/workflows/autopilot-create-issue.yml @@ -15,6 +15,7 @@ jobs: create-issue: if: ${{ github.event.workflow_run.conclusion == 'failure' }} runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: Create or update issue uses: actions/github-script@v9 diff --git a/.github/workflows/autopilot-docs-daily.yml b/.github/workflows/autopilot-docs-daily.yml index 670b0a9..09695a3 100644 --- a/.github/workflows/autopilot-docs-daily.yml +++ b/.github/workflows/autopilot-docs-daily.yml @@ -14,6 +14,7 @@ permissions: jobs: docs: runs-on: ubuntu-latest + timeout-minutes: 15 env: ORG: ${{ vars.ORG || github.repository_owner }} GH_TOKEN: ${{ secrets.ORG_READ_TOKEN || github.token }} diff --git a/.github/workflows/autopilot-operator.yml b/.github/workflows/autopilot-operator.yml index c6c1cf0..5a8cc25 100644 --- a/.github/workflows/autopilot-operator.yml +++ b/.github/workflows/autopilot-operator.yml @@ -13,6 +13,7 @@ permissions: jobs: operator: runs-on: [self-hosted, Windows] + timeout-minutes: 15 env: ORG: ${{ vars.ORG }} GH_TOKEN: ${{ secrets.ORG_AUTOPILOT_TOKEN }} diff --git a/.github/workflows/autopilot-org-installer.yml b/.github/workflows/autopilot-org-installer.yml index 60697e1..2d312bb 100644 --- a/.github/workflows/autopilot-org-installer.yml +++ b/.github/workflows/autopilot-org-installer.yml @@ -13,6 +13,7 @@ permissions: jobs: installer: runs-on: ubuntu-latest + timeout-minutes: 15 env: ORG: ${{ vars.ORG }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1def497..27c1752 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -4,10 +4,14 @@ on: branches: ["main", "master"] pull_request: branches: ["main", "master"] +permissions: + contents: read + jobs: analyze: name: Analyze runs-on: ubuntu-latest + timeout-minutes: 15 permissions: actions: read contents: read diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 0f43fae..276236a 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -14,6 +14,7 @@ concurrency: jobs: build: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v5 @@ -29,6 +30,7 @@ jobs: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest + timeout-minutes: 10 needs: build steps: - name: Deploy to GitHub Pages diff --git a/.github/workflows/pr-lint.yml b/.github/workflows/pr-lint.yml index 2f71474..afc713b 100644 --- a/.github/workflows/pr-lint.yml +++ b/.github/workflows/pr-lint.yml @@ -3,9 +3,14 @@ on: pull_request: types: ['opened', 'edited', 'reopened', 'synchronize'] +permissions: + contents: read + pull-requests: read + jobs: main: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: amannn/action-semantic-pull-request@v5 env: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 987cba1..6d4fb1b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -3,9 +3,15 @@ on: schedule: - cron: '30 1 * * *' +permissions: + contents: read + issues: write + pull-requests: write + jobs: stale: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/stale@v8 with: From e80eaab99948fed85f8a6e41d583a846b5bacb04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20Harjam=C3=A4ki?= Date: Sat, 4 Jul 2026 23:04:30 +0300 Subject: [PATCH 2/2] fix: extend operator timeout coverage --- .github/workflows/autopilot-operator.yml | 3 ++- memory/examples/20260704_operator-timeout-safe.md | 8 ++++++++ tests/contract-tests.ps1 | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 memory/examples/20260704_operator-timeout-safe.md diff --git a/.github/workflows/autopilot-operator.yml b/.github/workflows/autopilot-operator.yml index 5a8cc25..e46c88d 100644 --- a/.github/workflows/autopilot-operator.yml +++ b/.github/workflows/autopilot-operator.yml @@ -13,7 +13,8 @@ permissions: jobs: operator: runs-on: [self-hosted, Windows] - timeout-minutes: 15 + # Cover the intended batch work: clone, Codex, dependency install, and tests. + timeout-minutes: 60 env: ORG: ${{ vars.ORG }} GH_TOKEN: ${{ secrets.ORG_AUTOPILOT_TOKEN }} diff --git a/memory/examples/20260704_operator-timeout-safe.md b/memory/examples/20260704_operator-timeout-safe.md new file mode 100644 index 0000000..9a0bd14 --- /dev/null +++ b/memory/examples/20260704_operator-timeout-safe.md @@ -0,0 +1,8 @@ +# F-07 operator timeout safety + +Issue Description: The GitHub Actions operator job could time out after marking an issue `in-progress`, leaving it stranded until a later manual cleanup. +State: The workflow timeout was too short for the intended batch work of clone, Codex, dependency install, and tests. +Action: Increased `.github/workflows/autopilot-operator.yml` timeout to 60 minutes and added a contract assertion in `tests/contract-tests.ps1`. +Result: The operator job now has enough time for its designed batch work, and CI prevents the timeout from being reduced unnoticed. +Diff Patch: Updated the workflow timeout and added a workflow contract check. +Rationale: Batch automation should not strand claim-state on a predictable timeout boundary. diff --git a/tests/contract-tests.ps1 b/tests/contract-tests.ps1 index a1b00e1..9fed160 100644 --- a/tests/contract-tests.ps1 +++ b/tests/contract-tests.ps1 @@ -23,6 +23,7 @@ Assert-TextMatch -Text $operator -Pattern 'Assert-SafeChangeSet' -Message "Opera Assert-TextMatch -Text $operator -Pattern 'ALLOW_UNVERIFIED' -Message "Operator must enforce verification by default." Assert-TextMatch -Text $workflow -Pattern 'secrets\.ORG_AUTOPILOT_TOKEN' -Message "Workflow must use an explicit org mutation token." Assert-TextNotMatch -Text $workflow -Pattern 'GH_TOKEN: \$\{\{ secrets\.GITHUB_TOKEN \}\}' -Message "Workflow must not use repository token for org mutations." +Assert-TextMatch -Text $workflow -Pattern 'timeout-minutes: 60' -Message "Operator workflow must allow enough time for the intended batch work." Assert-TextNotMatch -Text $installer -Pattern 'autofix,queued,docs' -Message "Installer must not queue automation before repository opt-in."