This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow-steward.git
The following commit(s) were added to refs/heads/main by this push:
new 1307c8a feat(security): assign the signed-up owner / PR author on the
board — when syncing an issue or running a fix (#434)
1307c8a is described below
commit 1307c8ade9e74616820e6d30f407ff08713e7cba
Author: Jarek Potiuk <[email protected]>
AuthorDate: Tue Jun 2 03:33:29 2026 +0200
feat(security): assign the signed-up owner / PR author on the board — when
syncing an issue or running a fix (#434)
* feat(security-issue-sync): assign a signed-up volunteer (project member)
on the board
The Assignees rule already proposes the fix-PR author as assignee when
they are a project member. This adds the missing sign-up branch: when a
person volunteers to own the issue in a comment ("I'll take this",
"assign me", "I can work on the fix"), propose assigning them too —
gated on the same project-member check (security-team roster or
<tracker> collaborator).
- gather.md Step 1d: detect the volunteer-owner signal from comments.
- signals-to-actions.md Assignees: sign-up branch with the project-member
gate (a non-collaborator can't see the private tracker and GitHub drops
the assignee write — recorded as context, surfaced, never auto-assigned),
PR-author precedence when both exist, and no-override idempotency
(only when the issue has no assignee; hand-offs stay at fix-released).
No apply-step change — reuses the existing assignee-write path, so it
stays a propose-before-apply action behind the gh confirmation gate.
Generated-by: Claude Code (Opus 4.8)
* feat(security-issue-fix): assign the fix owner on the tracker (same rule
as sync)
Make the assignee behavior consistent across "syncing an issue" and
"running a fix". security-issue-fix Step 10 now has an explicit step to
assign the tracking issue to the fix owner once the PR exists — the
remediation developer (PR author), or a security-team member who signed
up to own it — reading the one Assignees rule from
security-issue-sync/signals-to-actions.md (project-member gate, never
override an existing assignee, hand-off stays at fix-released).
Pairs with the sync-side sign-up branch in the same branch. The
issue-fix-workflow skill is intentionally left untouched — it does not
write to the tracker or self-assign by contract.
Generated-by: Claude Code (Opus 4.8)
---
.claude/skills/security-issue-fix/SKILL.md | 31 +++++++++++++++++++---
.claude/skills/security-issue-sync/gather.md | 1 +
.../security-issue-sync/signals-to-actions.md | 27 +++++++++++++++++++
3 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/.claude/skills/security-issue-fix/SKILL.md
b/.claude/skills/security-issue-fix/SKILL.md
index 510d4aa..200cd3e 100644
--- a/.claude/skills/security-issue-fix/SKILL.md
+++ b/.claude/skills/security-issue-fix/SKILL.md
@@ -772,9 +772,34 @@ Now that a public PR exists, update the private tracking
issue:
in the [`security-issue-sync`](../security-issue-sync/SKILL.md)
skill.
-3. **Maintain milestones and labels** — see the next section.
-
-4. **Status update to the reporter** — if the <tracker> issue has an
+3. **Assign the tracker to the fix owner.** Now that a PR exists,
+ propose setting the tracking issue's assignee so the board
+ reflects who is on it. This applies the **same rule** as
+ `security-issue-sync` — the *Assignees* rule's PR-author and
+ sign-up branches in
+
[`security-issue-sync/signals-to-actions.md`](../security-issue-sync/signals-to-actions.md):
+ - The natural owner is the **remediation developer** — the
+ `<upstream>` PR author driving this fix.
+ - If a security-team member **signed up** to own the issue in the
+ thread, that volunteer is the owner instead (sign-up branch).
+ - **Project-member gate** (mandatory): assign only when the
+ person is on the security-team roster in
+
[`<project-config>/release-trains.md`](../../../<project-config>/release-trains.md)
+ or a `<tracker>` collaborator. A non-member is recorded and
+ surfaced but **not** assigned — they cannot see the private
+ tracker and GitHub silently drops the write.
+ - **Never override** an existing conflicting assignee here; the
+ hand-off to the release manager stays at the `fix released`
+ transition (sync owns it).
+
+ Propose; apply on confirmation. (The `security-issue-sync` run
+ this skill invokes also reconciles the assignee, so when sync
+ runs in the same pass this step and sync agree — they read the
+ one rule.)
+
+4. **Maintain milestones and labels** — see the next section.
+
+5. **Status update to the reporter** — if the <tracker> issue has an
identified external reporter and the reporter has not yet been
told about the fix PR, delegate to the `security-issue-sync`
skill's "Status update to the reporter" category by re-running
diff --git a/.claude/skills/security-issue-sync/gather.md
b/.claude/skills/security-issue-sync/gather.md
index deac461..0755856 100644
--- a/.claude/skills/security-issue-sync/gather.md
+++ b/.claude/skills/security-issue-sync/gather.md
@@ -308,6 +308,7 @@ update, label change, or next-step recommendation in Step 2:
|---|---|
| Reporter reply with a confirmed credit line (*"please credit me as …"*,
*"use handle X"*, *"anonymous is fine"*) | Replace the `Reporter credited as`
placeholder with the confirmed form; mark the credit question as resolved so
the next status-update draft does not re-ask it. |
| Reporter explicit opt-out of credit (*"do not credit me"*, *"anonymous"*) |
Set the field to `anonymous` and flag the advisory to use that form. |
+| A **project member signs up to own the issue** in a comment (*"I'll take
this"*, *"assign me"*, *"I can work on the fix"*, *"picking this up"*, *"I'll
drive the advisory"*) — distinct from the reporter and from a fix-PR author |
Record the volunteer's GitHub handle as a **prospective assignee** (the
*volunteer-owner* signal). In Step 2b, propose assigning them per the sign-up
branch of the **Assignees** rule in
[`signals-to-actions.md`](signals-to-actions.md), gated on their being a pr
[...]
| Release manager's `[RESULT][VOTE] Release Airflow <version>` on `<dev-list>`
for a version that carries the fix | Record the release manager in the "Known
release managers" subsection of [`AGENTS.md`](../../../AGENTS.md) if not
already there; flag Step 13 (advisory) as assigned to that person. |
| Open `[VOTE] Release <project> <version>` thread on
`dev@<project>.apache.org` for a version that matches the tracker's fix-PR
milestone, *and* the project has opted into release-vote gating
([`[workflow].release_vote_gating` in
`cve-json-config.toml`](../../../tools/cve-tool-vulnogram/generate-cve-json/SKILL.md))
| Propose adding the configured `rc voting` label (default name; see [Step
1h](#1h-detect-active-release-vote-threads-opt-in-asf-projects)). The label
feeds back into the CVE [...]
| Advisory archived on `<users-list>` (the announcement message is now visible
in `lists.apache.org/list.html?<users-list>` — scan the archive with the CVE ID
when `fix released` is set and the *"Public advisory URL"* body field is empty)
| This is the **post-advisory lifecycle close-out trigger**. Propose, in a
single combined apply: (1) populate the *"Public advisory URL"* body field with
the archive URL; (2) **extract the public-facing short summary from the
advisory email body** (the [...]
diff --git a/.claude/skills/security-issue-sync/signals-to-actions.md
b/.claude/skills/security-issue-sync/signals-to-actions.md
index ec7fc9f..b50f7c4 100644
--- a/.claude/skills/security-issue-sync/signals-to-actions.md
+++ b/.claude/skills/security-issue-sync/signals-to-actions.md
@@ -148,6 +148,33 @@ will change and *why*. Group them by category:
notifications. Instead, leave the assignee empty or propose a
security-team member who is already engaged in the discussion.
+ **Sign-up (volunteer) branch.** A fix PR is not the only ownership
+ signal. When a person has **signed up** to own the issue — the
+ *volunteer-owner* signal from
+ [`gather.md` Step
1d](gather.md#1d-mine-comments-and-mail-messages-for-actionable-signals)
+ (a comment volunteering to take it: *"I'll take this"*, *"assign
+ me"*, *"I can work on the fix"*, *"I'll drive the advisory"*) —
+ **propose setting that person as the assignee**, subject to the
+ **same project-member gate** as the PR-author branch: their handle
+ must appear in the security-team roster in
+
[`<project-config>/release-trains.md`](../../../<project-config>/release-trains.md),
+ or in `gh api repos/<tracker>/collaborators --jq '.[].login'`
+ (every permission level counts). The gate matters twice over for a
+ private tracker: a non-collaborator **cannot see the issue**, and
+ GitHub silently drops assignee writes for non-collaborators. So a
+ volunteer who is **not** a project member is recorded in the
+ proposal as context but **not** assigned — surface *"`<handle>`
+ volunteered but is not a `<tracker>` collaborator — invite them
+ first?"* and let the user decide. Precedence and idempotency:
+
+ - When both a sign-up and a fix-PR author exist, the **PR author
+ wins** — the in-flight fix is the stronger ownership signal;
+ record the volunteer as context only.
+ - Only propose the sign-up assignment when the issue currently has
+ **no assignee**. Never override an existing assignee on a
+ volunteer signal — that is a hand-off, which only happens at the
+ `fix released` transition below.
+
Also propose clearing a stale assignment if the person is no longer
active on the issue, and propose self-assigning a team member only
if the user explicitly asks.