Skip to content

ci: route codegen-oss PR CI to the pf-ci pool behind the canon authz job (#789) - #232

Open
luisleo526 wants to merge 2 commits into
mainfrom
ci/r789-codegen
Open

luisleo526 wants to merge 2 commits into
mainfrom
ci/r789-codegen

Conversation

@luisleo526

Copy link
Copy Markdown
Contributor

Apply owner ruling #789 and the single canon of ci-labels.md (L6 #808,
#819, #838-#840): all CI runs on our machines and only our own pull
requests and events run it.

Routing: gate.yml and test.yml use the literal array
["self-hosted","pf-ci","pf-ci-x64"] for their jobs, with no hosted fallback.
The Pyodide gate runs on pull_request, not pull_request_target.
Credential and release jobs are not touched and wait for pf-ci-release:
release.yml, publish-pyodide.yml, promote-baseline.yml.

Identity: gate.yml and test.yml start with the canon authz job, copied byte
for byte (workflow_run, pull_request and default arms; CONTRIBUTOR
permission lookup; ALLOWED_BOTS "dependabot[bot] pineforge-app[bot]";
permissions {}; no checkout, no secret). Every other job lists authz in
needs. No job-level same-repository skip remains: a skipped required check
counts as passing.

Aggregate: the gate job runs if: ${{ always() }}, never !cancelled(); its
first step is the canon refuse step, and every later step that runs
repository code carries if: needs.authz.result == 'success'.

Tests and docs: tests/test_pr_workflows.py pins the canon authz text, the
needs wiring, the refuse-first step, the always() aggregate, the labels and
the absence of hosted fallbacks, with must-fail mutations; CONTRIBUTING.md
states the rule and the repository setting it depends on.

ci-policy-check.py (14:53 version) reports R2 and R5 on the byte-identical
canon blocks: a known false positive, fixed in ci-policy r6. The remaining
R6/R1 findings are the credential and release jobs named above.

Rulesets: authz and gate are required status checks; the repository setting
for fork pull request workflows is read back by the repository owner.

Validation: NOT RUN (authored without executing anything); the PR's own CI
run on the pool is the proof.

Ruleset (to apply after merge, by CORE-TOP / L6)

Make authz and the repository's aggregate job(s) named above REQUIRED status checks, next to the checks the repository already requires (read the current list first: gh api read, keep it). No paths: or branches: filter exists on the pull_request trigger of the workflows that hold authz.

Repository setting the guard depends on (to be read back and quoted here by CORE-TOP)

  • Private repository: Settings > Actions > General > "Run workflows from fork pull requests" OFF.
  • Public repository: "Require approval for all external contributors"; the pf-ci runner group refuses public repositories.

authz is the second lock and the readable verdict; the dispatcher's identity gate (who gets a runner at all) is the first.

Known checker output

ci-policy-check.py (the 14:53 version) reports R2 and R5 on the byte-identical canon blocks (the canon authz script starts with set -eu; the canon refuse step has echo and exit 1 on two lines): "ci-policy-check R2/R5 false positive on the canon block, fixed in ci-policy r6". The remaining R6/R1 findings are the credential and release jobs left on purpose, waiting for pf-ci-release (listed above).

Security notes (automated review flagged the same points; none is new)

  • Jobs reachable from a pull request run on the self-hosted pool by owner ruling #789 (no GitHub-hosted fallback). The protections are the repository setting above, the dispatcher's identity gate, one job per VM, and the canon authz job; a fork cannot make authz pass because the setting keeps fork workflows from running.
  • Dependabot PRs run on the pool by owner decision CI-DEPBOT = A (same-repository dependabot[bot] only, in ALLOWED_BOTS).
  • Nothing in this PR touches a secret, a permission or a credential job.

Verification

NOT RUN by the author: nothing from this repository was executed on the authoring machine. The proof is this PR's own CI run on the pool (authz passes, every other job runs after it), plus a Codex read.

🤖 Generated with Claude Code

luisleo526 and others added 2 commits October 20, 2026 16:19
…job (#789)

Apply owner ruling #789 and the single canon of ci-labels.md (L6 #808,
#819, #838-#840): all CI runs on our machines and only our own pull
requests and events run it.

Routing: gate.yml and test.yml use the literal array
["self-hosted","pf-ci","pf-ci-x64"] for their jobs, with no hosted fallback.
The Pyodide gate runs on `pull_request`, not `pull_request_target`.
Credential and release jobs are not touched and wait for pf-ci-release:
release.yml, publish-pyodide.yml, promote-baseline.yml.

Identity: gate.yml and test.yml start with the canon authz job, copied byte
for byte (workflow_run, pull_request and default arms; CONTRIBUTOR
permission lookup; ALLOWED_BOTS "dependabot[bot] pineforge-app[bot]";
permissions {}; no checkout, no secret). Every other job lists authz in
needs. No job-level same-repository skip remains: a skipped required check
counts as passing.

Aggregate: the gate job runs `if: ${{ always() }}`, never !cancelled(); its
first step is the canon refuse step, and every later step that runs
repository code carries `if: needs.authz.result == 'success'`.

Tests and docs: tests/test_pr_workflows.py pins the canon authz text, the
needs wiring, the refuse-first step, the always() aggregate, the labels and
the absence of hosted fallbacks, with must-fail mutations; CONTRIBUTING.md
states the rule and the repository setting it depends on.

ci-policy-check.py (14:53 version) reports R2 and R5 on the byte-identical
canon blocks: a known false positive, fixed in ci-policy r6. The remaining
R6/R1 findings are the credential and release jobs named above.

Rulesets: authz and gate are required status checks; the repository setting
for fork pull request workflows is read back by the repository owner.

Validation: NOT RUN (authored without executing anything); the PR's own CI
run on the pool is the proof.

Documentation sentences replaced in CONTRIBUTING.md, quoted VERBATIM
from aebad8c (both complete sentences, each with 6+ consecutive words;
README.md and docs/**/*.md have no removed or rewritten sentences):

CONTRIBUTING.md:121:

> CI clears a pull request from a fork into `main` only when it changes
> documentation or legal text alone (Markdown, `docs/`, `LICENSE`, `NOTICE`).

CONTRIBUTING.md:123:

> A fork's code change does not run in CI here: its `gate` check fails until a
> maintainer pushes the branch to this repository and opens a pull request
> from it, which runs the full gate.

Superseded addendum-2 statements also rewritten by this correction,
quoted VERBATIM from the incoming worktree (6+ consecutive words each):

> For pull requests, CI runs only on same-repository branches; fork PRs run
> nothing, including documentation-only changes.

> Every PR-triggerable job uses the canonical same-repository guard,
> combined with any docs-only condition and with `always()` on the `gate`
> aggregate.

The replacement documents the literal-array rule, outside-fork approval
hold, required authz, dispatcher actor admission, a member's fork
failing red, preserved docs-only gate semantics and required contexts.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…16, #789)

A Codex read of this head found three `subprocess.run(..., timeout=5)` calls that this
change had added to the refusal-shell, authz-shell and aggregate-shell helpers
(tests/test_pr_workflows.py:1020, :1150, :1346). They run a correct shell and check its
exit code; a runner that is slow for five seconds would raise TimeoutExpired and fail the
required gate. EN-116 (#201) removed such deadlines on purpose: slowness never fails a
required check, and the platform job maximum is the only hang catcher. The three
`timeout=5` arguments are removed; nothing else changes.

Validation: NOT RUN here (nothing from the repository runs on the authoring machine);
the PR's CI re-run is the proof.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant