diff --git a/.claude/skills/sync-security-issue/SKILL.md b/.claude/skills/sync-security-issue/SKILL.md index f3e74256..b9a8666e 100644 --- a/.claude/skills/sync-security-issue/SKILL.md +++ b/.claude/skills/sync-security-issue/SKILL.md @@ -1410,6 +1410,132 @@ will change and *why*. Group them by category: single preformatted block and hiding every link. Do not indent entries for "readability". +- **Release-manager hand-off comment** — when this sync pass + proposes the `pr merged` → `fix released` label swap (Step 12), + **also** propose posting a separate hand-off comment that walks + the release manager through the rest of the lifecycle (Steps + 13–15) end-to-end, on a single tracker page, without forcing them + to consult the rollup or external docs. + + **This is its own first-class comment, not a rollup entry.** The + rollup is for the security team's audit trail and accumulates many + small entries; the hand-off comment is a one-shot orientation + surface for the release manager and must stay readable as a single + comment. Folding it into the rollup would bury the call-to-action + inside a `
` block. + + **Trigger.** Fires *exactly once* per tracker, at the same sync + pass that proposes `pr merged` → `fix released`. Do not propose it + earlier — the tracker is not yet the release manager's + responsibility before that swap, and a hand-off comment posted at + `cve allocated` or `pr merged` would lose context by the time the + release actually ships. Do not propose it on subsequent runs once + it has already been posted (idempotency check below). + + **Idempotency.** Before proposing, scan the issue's existing + comments for the marker + ``` + + ``` + exactly. If a comment carrying this marker already exists, **do + not propose a re-post** — surface as *"hand-off comment already + posted on `` (skipping)"* in the observed-state dump + and move on. The marker is on line 1 of the comment body so a + literal `gh issue view --json comments --jq` filter can detect it + cheaply. + + **Body source.** The comment body comes from the project's + configured CVE tool — the path is + `tools//release-manager-handoff-comment.md` where + `` is the value of `cve_tool` in + [`/project.md`](../../..//project.md#cve-tooling) + (for projects on Vulnogram, that resolves to + [`tools/vulnogram/release-manager-handoff-comment.md`](../../../tools/vulnogram/release-manager-handoff-comment.md)). + The template is parameterised; the substitutions the skill + performs are listed in the template's HTML-comment header. Do not + fork or paraphrase the template body in the proposal — load it + verbatim, substitute the placeholders, post. + + **Resolving placeholders.** All values come from configuration or + from the tracker itself, so there is no free-form drafting: + + - `CVE_ID` — from the tracker's *CVE tool link* body field. + - `RM_HANDLE` — looked up via the three-source cascade in Step 2c + (project's *Known release managers* / Release Plan wiki / dev@ + `[RESULT][VOTE]` thread). Same lookup the assignee swap uses; + do it once and reuse. + - `SECURITY_LIST`, `USERS_LIST`, `ANNOUNCE_LIST` — from + [`/project.md`](../../..//project.md#mailing-lists). + - `SOURCE_TAB_URL`, `EMAIL_TAB_URL` — substitute `` into + `cve_tool_record_url_template` (from project.md), append + `#source` / `#email` per [`tools/vulnogram/record.md`](../../../tools/vulnogram/record.md#record-urls). + - `JSON_ANCHOR_URL` — the deep link the `generate-cve-json` tool + prints on every regen (the + `https://github.com//issues/#cve-json--paste-ready-for-` + anchor). + - `ARCHIVE_SCAN_URL` — the project's PonyMail public-search URL + template (`ponymail_public_search_url_template` from project.md), + parameterised with the CVE ID. + - `FRAMEWORK_RECORD_MD_URL`, `FRAMEWORK_SYNC_SKILL_URL`, + `FRAMEWORK_README_URL` — absolute GitHub URLs into + `apache/airflow-steward` `main`, since the framework lives in a + submodule that does not render through the parent-repo viewer + (per the absolute-URL rule used elsewhere in this repo). + - `CANNED_RESPONSES_URL` — absolute GitHub URL into the tracker + repo's `/canned-responses.md`. + + **Apply mechanic** — see the *Release-manager hand-off comment* + bullet in Step 4 below; it is a fresh `gh issue comment`, not a + PATCH on the rollup. + + **Recap.** Surface the new comment URL in the recap (Step 6) so + the user can click through and verify the post. + +- **Publication-ready notification comment** — when this sync pass + proposes populating the *Public advisory URL* body field (Step 14 + — see the *Advisory archived on ``* row of the Step 1d + table), **also** propose posting a separate publication-ready + notification comment on the tracker. The comment tells the release + manager that the archive URL has been captured, the JSON has been + regenerated to include it as a `vendor-advisory` reference, and + the final paste + `READY` → `PUBLIC` move is now unblocked. + + **Why a second comment instead of one comment with two states.** + The hand-off comment posted at Step 12 has `READY` as its + rendered-final state and `PUBLIC` as a "wait for follow-up" + pointer. The follow-up is exactly this notification. Splitting + the call-to-action into two comments (rather than nudging the RM + to re-read step 7 of the same comment from days ago) gives the + RM a fresh, dated surface for the second action and a working + `@`-mention notification. + + **Trigger.** Fires *exactly once* per tracker, at the same sync + pass that proposes the *Public advisory URL* body update. Do not + propose it earlier (the URL is not yet captured) or repeatedly + (idempotency check below). + + **Idempotency.** Before proposing, scan the issue's existing + comments for the marker + ``` + + ``` + exactly. If a comment carrying this marker already exists, do not + re-post — surface as *"publication-ready comment already posted on + `` (skipping)"* and move on. + + **Body source.** Same load-from-tool-doc model as the hand-off + comment — the body comes from + `tools//release-manager-publication-comment.md` (for + Vulnogram: + [`tools/vulnogram/release-manager-publication-comment.md`](../../../tools/vulnogram/release-manager-publication-comment.md)). + Placeholders substituted: `CVE_ID`, `RM_HANDLE`, `ARCHIVE_URL` + (the just-captured archive URL), `SOURCE_TAB_URL`, + `JSON_ANCHOR_URL`, `CVE_ORG_URL` + (`https://www.cve.org/CVERecord?id=`). + + **Apply mechanic** — same as the hand-off comment: a fresh + `gh issue comment`, surfaced in the recap. + - **Draft email to reporter (other reasons)** — whenever the ball is in our court on the email thread for any other reason (a question from the reporter, a follow-up needed for triage, communicating a negative @@ -1597,7 +1723,48 @@ before moving on to the next item. Use: comment with `gh api -X DELETE repos//issues/comments/`. Never delete before the PATCH lands. +- **Release-manager hand-off comment:** load the body template from + `tools//release-manager-handoff-comment.md`, substitute + the placeholders (per the *Release-manager hand-off comment* + bullet in Step 2b), write the result to a temp file, then post: + + ```bash + gh issue comment --repo \ + --body-file + ``` + + This is a **fresh comment**, not a PATCH on the rollup. The + `` marker on + line 1 of the template is what subsequent sync runs grep for to + enforce idempotency — preserve it verbatim. Capture the new + comment URL from the post for the Step 6 recap. + + Before posting, **scrub the resolved body** for the same bare- + name → `@`-handle replacements documented for the rollup PATCH + above, so the `RM_HANDLE` substitution actually notifies the + release manager. +- **Publication-ready notification comment:** same recipe as the + hand-off comment above, but loading + `tools//release-manager-publication-comment.md`. The + marker is ``. + Apply right after the *Public advisory URL* body-field update has + landed and the CVE JSON has been regenerated (Step 5) — that way + the comment's *"the JSON has been regenerated to include the + archive URL"* claim is true at the moment the RM reads it. - **Close / reopen:** `gh issue close --repo --reason completed` (or `not planned`). + When this is a GitHub-backed tracker that uses a project board, + **always** follow a successful close with the **archive-from-board** + mutation per the *Archive a board item* recipe in + [`tools/github/project-board.md`](../../../tools/github/project-board.md#archive-a-board-item--terminal-state-cleanup). + Closed issues leave the active board view automatically, but an + explicit archive (`archiveProjectV2Item`) is what moves the item + to the board's *"Archived items"* view permanently — without it, + reopening a tracker resurfaces it on whatever column its `Status` + field still points at, and historical board sweeps still see the + item. Apply the archive for every close, regardless of the close + reason (terminal-Step-15 or non-terminal disposition like + `invalid` / `duplicate` / `not CVE worthy` / `wontfix`); the + mutation is idempotent and a no-op on already-archived items. - **Project-board column:** apply via the `updateProjectV2ItemFieldValue` GraphQL recipe in [`tools/github/project-board.md`](../../../tools/github/project-board.md#write--move-a-tracker-to-a-different-column). diff --git a/README.md b/README.md index e6f30d67..0e1894a8 100644 --- a/README.md +++ b/README.md @@ -885,6 +885,18 @@ this ownership hand-off implicit; splitting them makes it explicit and surfaces a `fix released` backlog the release manager can drive from the board. +**Hand-off comment.** The same `sync-security-issue` pass that proposes +the `pr merged` → `fix released` swap also proposes posting an explicit +**release-manager hand-off comment** on the tracker — a self-contained, +numbered checklist (steps 13–15 from the RM's perspective) that +@`-mentions the release manager and links to the paste-ready CVE JSON, +the Vulnogram `#source` and `#email` tabs, and the canned-response +templates. The comment is a one-shot, posted exactly once per tracker; +subsequent sync runs detect it via an HTML marker and skip the post. +This is a separate first-class comment, not a status-rollup entry — +the rollup is for the security team's audit trail, the hand-off is the +RM's call-to-action surface. + ### Step 13 — Send the advisory During releases, the release manager looks through `fix released` @@ -958,6 +970,19 @@ Until the *Public advisory URL* field is populated, the record's public `vendor-advisory` reference will point at, and publishing a CVE with an empty reference leaks a broken record into `cve.org`. +**Publication-ready notification comment.** The same sync pass that +populates the *Public advisory URL* body field also proposes posting a +**publication-ready notification comment** on the tracker — a separate +first-class comment that `@`-mentions the release manager, summarises +the deterministic updates that just landed (URL captured, JSON +regenerated, `announced` label added), and gives the explicit go-ahead +for the final paste + `READY` → `PUBLIC` move and tracker close. Like +the Step 12 hand-off comment, it is a one-shot posted exactly once +per tracker (idempotent on subsequent runs via an HTML marker). +Together the two comments form a two-part narrative the release +manager can drive from the tracker page without consulting the rollup +or external docs. + ### Step 15 — Publish the CVE record and close the issue **Push the final CVE record and close the issue.** For every issue @@ -969,11 +994,14 @@ same person who sent the advisory in Step 13): * copies the latest CVE JSON attachment from the tracking issue (the one regenerated in Step 14, now carrying the `vendor-advisory` URL) and pastes it into the `#source` form; -* saves and moves the record from `REVIEW` to `PUBLIC` in the ASF CVE +* saves and moves the record from `READY` to `PUBLIC` in the ASF CVE tool — **this is the final action** that propagates the record to [`cve.org`](https://cve.org); * **closes the issue** — do not update any labels. That closes - the lifecycle. + the lifecycle. The `sync-security-issue` skill follows the close + with an explicit `archiveProjectV2Item` mutation so the closed + tracker leaves the active board permanently + (see [`tools/github/project-board.md` — *Archive a board item*](tools/github/project-board.md#archive-a-board-item--terminal-state-cleanup)). This two-step hand-off (sync captures the URL → RM publishes the record) means nobody has to remember both halves: the sync skill's responsibility diff --git a/tools/github/project-board.md b/tools/github/project-board.md index dff10174..acde26ab 100644 --- a/tools/github/project-board.md +++ b/tools/github/project-board.md @@ -10,6 +10,10 @@ - [Introspection — re-fetch the option IDs](#introspection--re-fetch-the-option-ids) - [Write — move a tracker to a different column](#write--move-a-tracker-to-a-different-column) - [Orphan-issue path](#orphan-issue-path) + - [Archive a board item — terminal-state cleanup](#archive-a-board-item--terminal-state-cleanup) + - [Archive recipe](#archive-recipe) + - [Idempotency](#idempotency) + - [Inverse — unarchive](#inverse--unarchive) - [When the board is a no-op](#when-the-board-is-a-no-op) @@ -216,6 +220,71 @@ gh api graphql -f query=' # Step 3: move the newly-added item to the target column (see the write recipe above). ``` +## Archive a board item — terminal-state cleanup + +When a tracker reaches the terminal `closed` state of the lifecycle +(Step 15 of [`../../README.md`](../../README.md) — CVE record moved +to `PUBLIC`, tracker closed), the project-board item is no longer +useful as an active-work signal. Archive it from the board so the +active columns reflect only in-flight trackers. + +Archiving is an explicit Projects V2 mutation (`archiveProjectV2Item`) +that hides the item from the default board view. The item is *not* +deleted — it stays on the board's "Archived items" view and continues +to belong to the project. + +### Archive recipe + +```bash +gh api graphql -f query=' + mutation($pid:ID!,$iid:ID!) { + archiveProjectV2Item(input: { projectId: $pid, itemId: $iid }) { + item { id } + } + }' \ + -F pid= \ + -F iid= +``` + +The `pid` is the same `` used by the column-move +mutation in [*Write — move a tracker to a different column*](#write--move-a-tracker-to-a-different-column); +the `iid` is the same `` returned by the introspection +query (or freshly captured at apply time after `addProjectV2ItemById` +on a previously-orphan issue). + +### Idempotency + +Archiving an already-archived item returns success without changing +state — the mutation is idempotent on the second call. Skills that +re-run on closed trackers (for example, a backfill sweep on +historically-closed issues) can call `archiveProjectV2Item` without +detecting prior-archived state first. + +To detect whether an item is already archived (e.g. before a sync run +to avoid emitting a no-op log line), include `isArchived` in the +introspection query — when an item carries `isArchived: true`, skip +the archive call. + +### Inverse — unarchive + +If a tracker is reopened (rare; usually only when a closing +disposition is reverted), restore the item to the active board with: + +```bash +gh api graphql -f query=' + mutation($pid:ID!,$iid:ID!) { + unarchiveProjectV2Item(input: { projectId: $pid, itemId: $iid }) { + item { id } + } + }' \ + -F pid= \ + -F iid= +``` + +The unarchived item lands back on whatever column its `Status` field +points at; if the column needs to change too, follow with a regular +column-move mutation. + ## When the board is a no-op Not every GitHub-backed project runs a Projects V2 board. A project diff --git a/tools/vulnogram/record.md b/tools/vulnogram/record.md index 24967081..3ff43e84 100644 --- a/tools/vulnogram/record.md +++ b/tools/vulnogram/record.md @@ -8,6 +8,7 @@ - [State machine](#state-machine) - [Reviewer-comment signal](#reviewer-comment-signal) - [Record-generator round trip](#record-generator-round-trip) + - [Release-manager checklist](#release-manager-checklist) @@ -32,6 +33,16 @@ Per-project URL templates live in | Record page (human-readable + edit surface) | `https://cveprocess.apache.org/cve5/` | | `#source` tab (paste-the-JSON target) | `https://cveprocess.apache.org/cve5/#source` | | `#json` tab (rendered view of the stored JSON) | `https://cveprocess.apache.org/cve5/#json` | +| `#email` tab (preview the advisory email before sending) | `https://cveprocess.apache.org/cve5/#email` | + +The `#email` tab is the **email-preview** surface: it renders the +advisory exactly as Vulnogram will send it to `` and +`` — same subject, same body, same recipient list. +The release-manager checklist in +[the *Release-manager checklist* section below](#release-manager-checklist) +calls this out as a load-bearing checkpoint **before** hitting Send, +because the preview surfaces formatting issues (truncation, broken +markdown, missing patch links) that the JSON view does not. The ASF CVE tool requires ASF OAuth; non-security-team members can see a record only after it has moved to `PUBLIC` (at which point the @@ -60,33 +71,49 @@ and close the issue"* (step 15). On Vulnogram that decomposes into: ## State machine Vulnogram wraps every record in a `CNA_private` envelope whose -`state` field drives the visibility + CNA-feed push. The three +`state` field drives the visibility + CNA-feed push. The four states the generic skills interact with: | State | Set by | What it means | |---|---|---| | `DRAFT` | Allocation (initial state post-allocation) | Record exists, ID is reserved, but content is still being filled in. Not visible on `cve.org`. | | `REVIEW` | Release manager once the content is complete | Ready for CNA review. ASF CNA reviewers may leave reviewer comments at this point (see *"Reviewer-comment signal"* below). Still not on `cve.org`. | +| `READY` | Release manager once review feedback is addressed (or immediately after `REVIEW` if no feedback arrived) | Content is final and the record is staged for the advisory-send step. The advisory emails are dispatched from Vulnogram while in `READY`. Still not on `cve.org`. | | `PUBLIC` | Release manager as the terminal step | Record pushed to `cve.org`. World-readable. The generic tracking-issue lifecycle terminates at the `close` action once this state has been reached. | -**`DRAFT` → `REVIEW`** happens when all required fields are populated -and the advisory has been sent on the project's `announce` / -`users` list. The `generate-cve-json` tool decides `REVIEW` versus -`DRAFT` by inspecting whether the tracker's *public-advisory-url* -body field is populated and whether a `vendor-advisory` reference -landed in the generated `references[]`; see the -*`_is_cna_ready_for_review`* helper in `generate-cve-json/src/…/cve_json.py` -for the exact predicate. +**`DRAFT` → `REVIEW`** happens when all required fields are populated. +The release manager moves the record to `REVIEW` after the first +JSON paste, opening the window for CNA reviewers to leave comments. + +**`REVIEW` → `READY`** happens once any reviewer comments have been +addressed (via the body-field round-trip described in the +*Record-generator round trip* section below), or immediately after +`REVIEW` when no comments arrive. `READY` is the state Vulnogram +expects when the release manager triggers the advisory email send. -**`REVIEW` → `PUBLIC`** is a human release-manager click in Vulnogram +**`READY` → `PUBLIC`** is a human release-manager click in Vulnogram after the advisory archive URL has been captured on the tracker. The generic `sync-security-issue` skill's Step 2b does not propose this -transition — it is a Step 15 release-manager action. +transition — it is a Step 15 release-manager action. The +publication-ready notification comment (see +[*Release-manager checklist*](#release-manager-checklist) below) +gives the RM the explicit go-ahead. `PUBLISHED` is sometimes used as a synonym for `PUBLIC` in older Vulnogram documentation; the current action is literally labelled `PUBLIC` in the UI. +The `generate-cve-json` tool decides `REVIEW` versus `DRAFT` for the +generated `CNA_private.state` field by inspecting whether the tracker's +*public-advisory-url* body field is populated and whether a +`vendor-advisory` reference landed in the generated `references[]`; +see the *`_is_cna_ready_for_review`* helper in +`generate-cve-json/src/…/cve_json.py` for the exact predicate. The +`READY` state itself is set by hand in Vulnogram after the +post-`REVIEW` body-field stabilisation — the generator does not emit +`READY` directly because it cannot tell, from the tracker body alone, +whether reviewer comments are still pending. + ## Reviewer-comment signal ASF CNA reviewers leave comments on `REVIEW`-state records. Those @@ -130,3 +157,78 @@ the embedded CVE JSON in the tracker body stays in lock-step with the body fields — every sync, every allocate-CVE wire-back, every dedupe merge regenerates the attachment. The release manager then has one canonical JSON to paste into `#source` at step 15. + +## Release-manager checklist + +When the `` release containing a fix ships, the +`sync-security-issue` skill swaps the tracker's `pr merged` label to +`fix released`, reassigns the issue to the release manager, and posts +an explicit **release-manager hand-off comment** on the tracker (the +template body lives in +[`release-manager-handoff-comment.md`](release-manager-handoff-comment.md)). +The numbered checklist below is the standalone authoritative recipe +the comment links to — keep them in lock-step when one changes. + +The flow has **two pastes** in the common case (no reviewer comments) +and **three** when reviewer comments arrive: + +1. **First paste — `DRAFT` → `REVIEW`.** Open the `#source` tab on + the CVE record. Copy the CVE JSON embedded in the tracking issue + (regenerated by `generate-cve-json` on every sync — see + [*Record-generator round trip*](#record-generator-round-trip) + above). Paste, **Save**. Move the record `DRAFT` → `REVIEW` via + the Vulnogram UI. + +2. **(conditional) Re-paste after reviewer comments.** ASF CNA + reviewers may leave comments while the record sits in `REVIEW` + (see [*Reviewer-comment signal*](#reviewer-comment-signal) above). + The `sync-security-issue` skill detects them automatically and + proposes matching body-field updates on the tracker; the security + team confirms and the embedded JSON regenerates. Once the body has + settled (no more pending reviewer-comment proposals), re-paste the + regenerated JSON into `#source` and **Save**. **Skip this step if + no reviewer comments arrived** (the common case for well-formed + records). + +3. **Set `READY`.** Vulnogram UI action — moves the record from + `REVIEW` to `READY` and stages it for the advisory-send step. + +4. **Preview the advisory email** on the + [`#email` tab](#record-urls). The preview renders the advisory + exactly as Vulnogram will send it — same subject, same body, same + recipient list. The preview is the load-bearing checkpoint for + formatting issues (truncation, broken markdown, missing patch + links) that the JSON view does not surface. **Always preview + before sending.** If anything needs to change, edit the + corresponding body field on the tracker, wait for the JSON to + regenerate, re-paste in `#source`, and re-preview. + +5. **Send the advisory emails.** Vulnogram dispatches to + `` and ``. On the tracker, add the + `announced - emails sent` label and remove `fix released`. + +6. **Wait for the publication-ready notification comment.** The + `sync-security-issue` skill scans the public users-list archive + for the CVE ID on every run. Once it finds the archived advisory, + it populates the tracker's *Public advisory URL* body field, + regenerates the CVE JSON to carry the archive URL as a + `vendor-advisory` reference, adds the `announced` label, **and + posts a publication-ready notification comment** on the tracker + (the template body lives in + [`release-manager-publication-comment.md`](release-manager-publication-comment.md)). + That comment is the explicit go-ahead for steps 7-8. + +7. **Second paste — `READY` → `PUBLIC`.** *Only after the + publication-ready notification fires.* Re-open `#source`, paste + the now-final JSON (carrying the archive URL in `references[]`), + **Save**, move the record `READY` → `PUBLIC` via the Vulnogram UI. + The record propagates to `cve.org` once the state lands. + +8. **Close the tracker.** Close as completed; do not update any + labels. The `sync-security-issue` skill's apply step archives the + project-board item afterwards (per the *archive-from-board* recipe + in [`../github/project-board.md`](../github/project-board.md)) + so the closed tracker leaves the active board. + +The "twice paste" framing in the hand-off comment maps to steps 1 and +7 of the checklist above; step 2 is the rare conditional middle paste. diff --git a/tools/vulnogram/release-manager-handoff-comment.md b/tools/vulnogram/release-manager-handoff-comment.md new file mode 100644 index 00000000..37f227ad --- /dev/null +++ b/tools/vulnogram/release-manager-handoff-comment.md @@ -0,0 +1,82 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [🚀 Release-manager hand-off — `CVE_ID`](#-release-manager-hand-off--cve_id) + - [Step-by-step](#step-by-step) + + + + + +` until the schema actually changes — the + skill's grep is anchored on `v1`. +--> + + +## 🚀 Release-manager hand-off — `CVE_ID` + +RM_HANDLE, the release containing the fix has shipped — this tracker +now belongs to you. The Vulnogram-specific recipe lives in +[`tools/vulnogram/record.md` — *Release-manager checklist*](FRAMEWORK_RECORD_MD_URL); +the high-level numbered checklist below is here for at-a-glance +reference without leaving this issue. + +The paste-ready CVE JSON is embedded in this tracker's +[issue body](JSON_ANCHOR_URL) and is regenerated automatically on +every body change by the [`sync-security-issue`](FRAMEWORK_SYNC_SKILL_URL) skill. + +### Step-by-step + +1. **First paste — `DRAFT` → `REVIEW`.** Open the [`#source` tab](SOURCE_TAB_URL) on the CVE record. Copy the embedded JSON from the tracker body above, paste into the form, **Save**. Move the record `DRAFT` → `REVIEW` via the Vulnogram UI. +2. **Wait for CNA review.** Reviewer comments arrive by email on `SECURITY_LIST` with the CVE ID in the subject line. The `sync-security-issue` skill detects them automatically and proposes matching body-field updates on this tracker; the security team confirms and the embedded JSON regenerates. **If no reviewer comments arrive (common case), skip to step 4.** Otherwise, once the body has settled, re-paste the regenerated JSON into `#source` and **Save** again. +3. **Set `READY`.** Vulnogram UI action — the record is now ready for the advisory-send step. +4. **Preview the advisory email** on the [email tab](EMAIL_TAB_URL) of the CVE record. Inspect how the email will render: subject, body, recipient list. The preview surfaces formatting issues (truncation, broken markdown, missing patch links) that the JSON view does not. If anything needs to change, edit the corresponding body field on this tracker, wait for the JSON to regenerate, re-paste in `#source`, and re-preview before sending. +5. **Send advisory emails** from Vulnogram. The form sends to `USERS_LIST` and `ANNOUNCE_LIST`. Then on this tracker, add the `announced - emails sent` label and remove `fix released`. +6. **(automatic) Archive URL captured.** The `sync-security-issue` skill scans the [users-list archive](ARCHIVE_SCAN_URL) for the CVE ID on every run. Once it finds the advisory, it populates the *Public advisory URL* body field, regenerates the CVE JSON to carry the archive URL as a `vendor-advisory` reference, and adds the `announced` label — **and posts a follow-up comment on this tracker** giving you the explicit go-ahead for the final paste below. +7. **Second paste — `REVIEW` → `PUBLIC`.** *Only after the follow-up comment in step 6 fires.* Re-open [`#source`](SOURCE_TAB_URL), paste the now-final JSON (carrying the archive URL in `references[]`), **Save**, move `REVIEW` → `PUBLIC` via the Vulnogram UI. The record propagates to `cve.org` once the state lands. +8. **Close the tracker** — close as completed; do not update any labels. The `sync-security-issue` skill archives the project-board item so the closed tracker leaves the active board. + +--- + +**References:** + +- Vulnogram state machine + paste flow: [`tools/vulnogram/record.md`](FRAMEWORK_RECORD_MD_URL). +- Reusable email wording (if you draft anything by hand): [`canned-responses.md`](CANNED_RESPONSES_URL). +- Full lifecycle (Steps 12-15): [`README.md`](FRAMEWORK_README_URL#for-release-managers--steps-1215). diff --git a/tools/vulnogram/release-manager-publication-comment.md b/tools/vulnogram/release-manager-publication-comment.md new file mode 100644 index 00000000..e65b1210 --- /dev/null +++ b/tools/vulnogram/release-manager-publication-comment.md @@ -0,0 +1,64 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [📰 Advisory archived — ready for `PUBLIC`](#-advisory-archived--ready-for-public) + + + + + + + + +## 📰 Advisory archived — ready for `PUBLIC` + +RM_HANDLE, the advisory you sent in step 5 of the hand-off above has +been archived on the public users-list. This sync pass made the +following deterministic updates on this tracker: + +- **Public advisory URL** body field populated: [ARCHIVE_URL](ARCHIVE_URL) +- The embedded CVE JSON regenerated to include the archive URL as a + `vendor-advisory` reference in `references[]`. +- The `announced` label added. + +You can now do the final paste + state move: + +1. Open the [`#source` tab](SOURCE_TAB_URL) on the CVE record. +2. Copy the regenerated JSON from this tracker's [issue body](JSON_ANCHOR_URL) and paste into the form. **Save**. +3. Move the record `REVIEW` → `PUBLIC` via the Vulnogram UI. The record propagates to [`cve.org`](CVE_ORG_URL) once the state lands. +4. **Close this tracker** — close as completed; do not update any labels. The `sync-security-issue` skill archives the project-board item afterwards. + +That terminates the lifecycle. Thanks for driving this one.