You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -155,7 +155,7 @@ The action exposes `signature_recorded=true` only after it persists a new signat
155
155
156
156
The action exposes `cla_passed=true` only after the write-capable signer has confirmed that every required contributor is signed and successfully applied the final all-signed CLA bot comment. It remains `false` for signer-preflight, unsigned, closed, and error runs. `signature_recorded=true` only means that this run persisted one new signature, so it can be true while `cla_passed` remains false for another unsigned contributor. `cla_passed` is a per-run result, not durable authorization; consumers must also require the writer job to succeed.
157
157
158
-
For a least-privilege admission gate, run the action with `mode: signer-preflight` in a separate job that has only `contents: read`, `pull-requests: read`, and `issues: read`. The GraphQL commit identity connection requires `contents: read` in private repositories. The mode re-fetches the live Pull Request, resolves the current author/co-author/committer identities through the same bounded GraphQL query as the signer, and verifies the event comment against the canonical unedited comment. It sets `signer_authorized=true` only for a matching account ID and emits the validated head and base commits as `head_sha` and `base_sha`. It also emits `comment_id`, `comment_created_at`, and `comment_author_id` for the exact declaration it authenticated. Pass those three outputs to the writer's `expected-comment-id`, `expected-comment-created-at`, and `expected-comment-author-id` inputs. The writer re-fetches that exact comment before every ledger or Pull Request comment write and accepts no replacement declaration. Inspect `signer_decision` to distinguish `authorized`, an exact declaration accepted by identity policy, from `unauthorized`, an exact declaration rejected by identity policy, and `error`, a validation or GitHub request failure. The action fails the job for both non-authorized decisions. Run the write-capable signer only when `signer_authorized` is `'true'`. Pass both SHA outputs to its `expected-head-sha` and `expected-base-sha` inputs. The writer compares all five values with the live Pull Request and comment before any ledger or comment write and on every later revalidation, so a force-push, base-branch advance, edited comment, or replacement comment fails closed. The write-capable signer must still perform its own live validation after the gate because preflight outputs are ephemeral admission results, not durable authorization tokens.
158
+
For a least-privilege admission gate, run the action with `mode: signer-preflight` in a separate job that has only `contents: read`, `pull-requests: read`, and `issues: read`. The GraphQL commit identity connection requires `contents: read` in private repositories. The mode re-fetches the live Pull Request, resolves the current primary author identities through the same bounded GraphQL query as the signer, and verifies the event comment against the canonical unedited comment. It sets `signer_authorized=true` only for a matching account ID and emits the validated head and base commits as `head_sha` and `base_sha`. It also emits `comment_id`, `comment_created_at`, and `comment_author_id` for the exact declaration it authenticated. Pass those three outputs to the writer's `expected-comment-id`, `expected-comment-created-at`, and `expected-comment-author-id` inputs. The writer re-fetches that exact comment before every ledger or Pull Request comment write and accepts no replacement declaration. Inspect `signer_decision` to distinguish `authorized`, an exact declaration accepted by identity policy, from `unauthorized`, an exact declaration rejected by identity policy, and `error`, a validation or GitHub request failure. The action fails the job for both non-authorized decisions. Run the write-capable signer only when `signer_authorized` is `'true'`. Pass both SHA outputs to its `expected-head-sha` and `expected-base-sha` inputs. The writer compares all five values with the live Pull Request and comment before any ledger or comment write and on every later revalidation, so a force-push, base-branch advance, edited comment, or replacement comment fails closed. The write-capable signer must still perform its own live validation after the gate because preflight outputs are ephemeral admission results, not durable authorization tokens.
159
159
160
160
The action publishes an all-signed bot comment only after it revalidates the signing comments and persists any new signatures. If a signer edits or deletes the declaration during the run, the ledger and the previous trusted bot status stay unchanged.
161
161
@@ -219,12 +219,12 @@ The action re-fetches accepted signing comments immediately before a ledger writ
219
219
220
220
CLA action workflow will be triggered on Pull Request `opened, edited, closed, reopened, synchronize, ready_for_review` events. This workflow will always run in the base repository and that's why we are making use of the [pull_request_target](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request_target) event. The action validates the live Pull Request state, opener, base repository ID, base branch, head repository ID, head branch, and head commit before it writes signature data.
221
221
222
-
The action fails closed for every unlinked committer, including metadata that claims to be `GitHub <noreply@github.com>` or `web-flow`. Git names and email addresses are not authenticated and can be forged. `allowlist-ids` cannot match an unresolved identity.
222
+
The action fails closed for every unlinked primary commit author. Git names and email addresses are not authenticated and can be forged, and `allowlist-ids` cannot match an unresolved identity. The git committer field is ignored entirely: it records who applied a commit (a maintainer, GitHub's `web-flow` merge, a rebase tool), not who holds the copyright, so `GitHub <noreply@github.com>` merge commits from the "Update branch" button never block a check.
223
223
224
-
GitHub can map an author, co-author, or committer email to an account ID, but this mapping does not authenticate authorship. Every non-opener identity from git metadata must post the exact declaration on the current Pull Request. A stored signature is reusable only for the account authenticated by the live Pull Request API as the opener. A committer-only match does not satisfy the opener author/co-author guard.
224
+
Signers are the authenticated Pull Request opener plus every primary commit author that GitHub maps to an account. A ledger signature belongs to an account ID and is reused in every later Pull Request, whichever role that account plays. `Co-authored-by` trailers are unverified text that commonly names pairing partners and AI coding agents; they satisfy the opener author/co-author guard but never create a signing obligation. A committer-only match does not satisfy the opener guard.
225
225
<br/> When the CLA workflow is triggered on pull request `closed` event and the Pull Request was merged, it will lock the Pull Request conversation with GitHub's `resolved` reason so that the contributors cannot modify or delete the signatures (Pull Request comment) later. The action re-fetches the closed Pull Request and matches its immutable base repository, base branch, opener, and merge state. A later source branch advance or deletion does not prevent locking. This feature is optional. A failed lock request fails the action. The action never removes a conversation lock. A maintainer must unlock a reopened Pull Request before contributors can sign.
226
226
227
-
The action fails closed when a Pull Request has more than 1,000 commits, more than 101,000 git identity assertions, more than 1,000 comments, or combined comment bodies over 10,000,000 UTF-8 bytes. Bodies over 65,536 UTF-8 bytes are discarded as non-matching comments because signing declarations must match the complete short phrase exactly, but their bytes still count toward the aggregate response bound. Invalid comment data fails closed. The identity bound is the finite envelope of 1,000 commits with up to 100 author/co-author identities plus one committer assertion per commit. A signature ledger also fails closed above 10,000 entries or 1,000,000 bytes. The byte limits bound the validated response data before any downstream comment or ledger writes. These limits bound work on untrusted Pull Request and ledger data. Split a larger contribution or start a new versioned ledger before running the CLA check.
227
+
The action fails closed when a Pull Request has more than 1,000 commits, more than 100,000 git identity assertions, more than 1,000 comments, or combined comment bodies over 10,000,000 UTF-8 bytes. Bodies over 65,536 UTF-8 bytes are discarded as non-matching comments because signing declarations must match the complete short phrase exactly, but their bytes still count toward the aggregate response bound. Invalid comment data fails closed. The identity bound is the finite envelope of 1,000 commits with up to 100 author/co-author identities per commit. A signature ledger also fails closed above 10,000 entries or 1,000,000 bytes. The byte limits bound the validated response data before any downstream comment or ledger writes. These limits bound work on untrusted Pull Request and ledger data. Split a larger contribution or start a new versioned ledger before running the CLA check.
228
228
229
229
#### 3. Signing the CLA
230
230
@@ -262,7 +262,7 @@ and `remote-repository-name`: `<your repo name>` in your CLA workflow file.
262
262
263
263
#### 5. Authenticated opener ID allowlist
264
264
265
-
Use `allowlist-ids`only when a specific automated Pull Request opener must be exempt. Values are comma-separated numeric GitHub database IDs. The action applies an exemption only when the live Pull Request API authenticates that ID as the opener, and then bypasses only the opener-authorship hard-fail. It never exempts an author, co-author, or committer derived only from git metadata. The deprecated `allowlist` name, email, and glob input is ignored because commit metadata can spoof those values.
265
+
Use `allowlist-ids` for maintainers and documented automation accounts that never need to sign. Values are comma-separated numeric GitHub database IDs. A configured ID is exempt as the Pull Request opener and as a primary commit author, and an allowlisted opener also bypasses the opener-authorship hard-fail. Unlinked identities have no ID and can never match. The deprecated `allowlist` name, email, and glob input is ignored because commit metadata can spoof those values.
266
266
267
267
##### Demo for step 5
268
268
@@ -298,7 +298,7 @@ Do not configure `PERSONAL_ACCESS_TOKEN` when signatures stay in the current rep
298
298
| `expected-comment-id` | _optional_ | REST ID of the exact signing comment emitted by `signer-preflight`. Set this together with the creation timestamp and author ID to prevent a writer from accepting another exact declaration on the same Pull Request. | `${{ steps.preflight.outputs.comment_id }}` |
299
299
| `expected-comment-created-at` | _optional_ | Exact creation timestamp emitted by `signer-preflight` for the authenticated signing comment. Required when `expected-comment-id` is set. | `${{ steps.preflight.outputs.comment_created_at }}` |
300
300
| `expected-comment-author-id` | _optional_ | Numeric GitHub account ID emitted by `signer-preflight` for the authenticated signing comment. Required when `expected-comment-id` is set. | `${{ steps.preflight.outputs.comment_author_id }}` |
301
-
|`allowlist-ids`| _optional_ | Comma-separated numeric GitHub user IDs. Only the authenticated live Pull Request opener can be exempt. Commit-derived identities are never exempt. |Leave empty unless a documented automated opener was reviewed. |
301
+
| `allowlist-ids` | _optional_ | Comma-separated numeric GitHub user IDs that never need to sign, as the opener or as a primary commit author. Unlinked identities cannot match. | Maintainer and reviewed automation account IDs. |
302
302
| `allowlist` | _deprecated_ | Ignored. Raw names, emails, and globs are unsafe identity evidence. | |
303
303
| `remote-repository-name` | _optional_ | provide the remote repository name where all the signatures should be stored . | remote repository name |
304
304
| `remote-organization-name` | _optional_ | provide the remote organization name where all the signatures should be stored. | remote organization name |
@@ -316,7 +316,7 @@ Do not configure `PERSONAL_ACCESS_TOKEN` when signatures stay in the current rep
316
316
317
317
| Name | Description |
318
318
| --------------------- | ----------- |
319
-
| `signer_authorized` | In `signer-preflight` mode, set to `'true'` only when the current newly-created, exact, unedited declaration is authored by an authenticated identity in the live Pull Request's author, co-author, committer, or opener set. The write-capable signer must repeat its live checks; this output is not a bearer authorization token. |
319
+
|`signer_authorized`| In `signer-preflight` mode, set to `'true'` only when the current newly-created, exact, unedited declaration is authored by an authenticated identity in the live Pull Request's primary author or opener set. The write-capable signer must repeat its live checks; this output is not a bearer authorization token. |
320
320
| `cla_passed` | Set to `'true'` only after the write-capable signer has confirmed that every required contributor is signed and successfully applied the final all-signed CLA bot comment. It is `'false'` for signer-preflight, unsigned, closed, and error runs. It is independent of `signature_recorded`, which can be `'true'` while another contributor remains unsigned. |
321
321
| `signer_decision` | In `signer-preflight` mode, `authorized` means the declaration passed identity policy, `unauthorized` means an exact current declaration failed identity policy, and `error` means validation or a GitHub request failed. The action fails the job for both `unauthorized` and `error`; in `sign` mode it remains `error`. |
322
322
| `head_sha` | In `signer-preflight` mode, the exact live Pull Request head SHA observed after validation. Pass it to the writer as `expected-head-sha` to reject a force-push between jobs. |
0 commit comments