This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch docs/release-guidelines-rewrite
in repository https://gitbox.apache.org/repos/asf/struts-site.git

commit 1fce5a11f8e3d353ab22fdd7bdbde6d1613f6435
Author: Lukasz Lenart <[email protected]>
AuthorDate: Fri Aug 14 13:16:41 2026 +0200

    docs: rewrite the release guidelines as the current release process
    
    The Release Process section described a process that has not been run in
    years: an Ant "release" target, Cactus tests, a test build posted to
    svn.apache.org/struts/, and a release plan on wiki.apache.org. The only
    end-to-end description of how a release is actually made was the cwiki
    page "Building Struts 2 - Normal release", last revised in 2017, which
    is right about JIRA, the release plugin, Nexus and dist.apache.org and
    wrong about everything downstream from there.
    
    Replace it with the seven-phase process the 7.3.0 and 6.11.0 releases
    were made with - prepare, cut, stage, vote, promote, publish, advisories
    - each with a gate that someone other than the release manager can
    verify, and with the commands needed at each step. Notably: releases are
    cut on a release/X.Y.Z-RC1 branch rather than on the line branch, the
    maven-release-plugin takes no command-line flags now that they live in
    the pom, the SCM tag prompt needs STRUTS_X_Y_Z typed by hand, and the
    site update is a pull request rather than an svn commit to a production
    checkout that no longer exists.
    
    Drop the Coding Conventions and Clarifications sections in favour of a
    pointer to the coding standards page, which covers the same ground and
    is maintained.
    
    This page is now the source of truth for the process; the cwiki pages
    will be replaced with pointers to it.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
---
 source/release-guidelines.md | 490 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 396 insertions(+), 94 deletions(-)

diff --git a/source/release-guidelines.md b/source/release-guidelines.md
index ef3611478..97f78c92b 100644
--- a/source/release-guidelines.md
+++ b/source/release-guidelines.md
@@ -9,104 +9,406 @@ title: Release Guidelines
 * Will be replaced with the ToC, excluding a header
 {:toc}
 
-This document describes the Apache Struts release process and our [coding 
conventions](#Coding),
-which are applicable to all subprojects. Both stable and development releases 
are
-[available for download.](releases)
+This document describes how an Apache Struts release is made: the policy that 
governs it, the
+seven phases it runs through, and the command needed at each step. It is 
written for the release
+manager, but every committer is encouraged to read it — releases are easier 
when more than one
+person knows what the next step is.
 
-## Release Process
+This page is the source of truth for the release process. Where an older wiki 
page disagrees
+with it, this page is current. For coding conventions see [Coding 
standards](coding-standards),
+and for building the framework day to day see [Builds](builds).
+
+## Release policy
 
 A [point release](http://commons.apache.org/releases/versioning) should be 
made before and after
-any product change that is not a "fully-compatible change" (see link). This 
includes moving a dependency from
-an internal package to an external product, including products distributed 
through the Apache Commons.
-We should place any fully-compatible changes in the hands of the community 
before starting on a change that
-is only "interface" or "external-interface" compatible.
-
-Additional remarks:
-
-- Every committer is encouraged to participate in the release process, either 
as the release manager or a
-  helper. Committers may also share the release manager role.
-- The release process can seem daunting when you review it for the first time. 
But, essentially, it breaks
-  down into four phases of just a few steps each:
-  - **Rolling** - Issues, dependencies, release notes, JAR manifest, licenses, 
copyrights,
-    and build (using the release target).
-  - **Testing** - JUnit, Cactus, web apps (for all "supported" containers).
-  - **Voting** - Upload test build to internal directory, post majority vote 
on DEV list as to release
-    grade: Alpha, Beta, General Availability.
-  - **Distributing** - Checksum, sign, mirror, update download page, announce.
-- Committers are **required** to post a release plan before tagging the 
repository and should wait
-  the traditional 72 hours before proceeding.
-- A checklist format can be used for the [release 
plan](http://wiki.apache.org/struts/StrutsReleasePlans),
-  to help step through the process. The plan may be maintained in the 
repository or on the
-  [Struts wiki](http://wiki.apache.org/struts/).
-- Our dependencies on external JARs (including Commons JARs) should be in line 
with our own release status.
-  Our nightly build can be dependant on another nightly build. Our beta can be 
dependant on another beta (or
-  "release candidate"), but should avoid a dependance on a nightly build. Our 
General Availability release
+any product change that is not a "fully-compatible change" (see link). We 
should place any
+fully-compatible changes in the hands of the community before starting on a 
change that is only
+"interface" or "external-interface" compatible.
+
+- Every committer is encouraged to participate in the release process, either 
as the release
+  manager or a helper. Committers may also share the release manager role.
+- Our dependencies should be in line with our own release status. A General 
Availability release
   may only have dependencies on other GA, final, or stable releases.
-- Use your own discretion as to detail needed by the Release Notes. A 
high-level description of the changes
-  is more important than providing uninterpreted detail. At a minimum, new 
features and deprecations should be
-  summarized, since these are commonly asked questions. Ideally, the release 
notes should be maintained,
-  continuously for the nightly build so that we they do not need to be 
assembled at the last minute.
-- Try building the distribution under prior version of J2SE, if possible, to 
ensure that we are still
-  backwardly-compatible. But, our distributions should be built using the 
**latest production release of J2SE**,
-  to take advantage of all available compiler enhancements.
-- If you have multiple J2SE versions configured, run the JUnit and Cactus 
tests using the same configuration
-  that will be used to build the distribution.
-- There is a "release" target in the buildfile that will zip and tar the 
distribution. Before uploading the
-  distribution, extract the sample web applications and deploy the WARs under 
each of the "supported"
-  containers (if you can). Play test each application under each container to 
be sure they operate
-  nominally.
-- The test build can be posted to the internal distribution directory 
(svn.apache.org/struts/) and
-  announced to the Struts DEV and PMC lists (only!). Do not announce a test 
build on any other Apache lists or
-  link to it from an Apache website.
-- If the test build is voted to Alpha, Beta, or GA status, the release can 
announced to the User list and
-  linked from the website.
+- Provide high-level API compatibility for any changes made within the same 
major release series
+  (`#.x.x`). Changes which adversely affect compatibility should be slotted 
for the next major
+  release series.
+- Use your own discretion as to the detail needed in the Version Notes. A 
high-level description
+  of the changes is more important than uninterpreted detail. At a minimum, 
new features and
+  deprecations should be summarised, since these are commonly asked questions.
 - Any formal release may be submitted for mirroring. All GA releases **must** 
be mirrored.
-- After announcing a release, remember to update the Downloads and 
Announcements pages. If the release is
-  to be mirrored, wait at least 24 hours after submittal before making public 
announcements (as stated in the
-  [Apache Mirroring guidelines](https://www.apache.org/dev/mirrors).
-- If a serious flaw if found in a test build or release, it may be withdrawn 
by a majority vote of the PMC and
-  removed from ASF distribution channels.
-
-## Coding Conventions and Guidelines
-
-Source code and documentation contributed to the Struts repositories should 
observe the:
-- The ["Code Conventions for the Java Programming 
Language"](http://www.oracle.com/technetwork/java/codeconvtoc-136057),
-  as published by Oracle.
-
-## Clarifications
-- First, "Observe the style of the original". Resist the temptation to make 
stylistic changes for their own
-  sake. But, if you must reformat code, commit style changes separately from 
code changes. Either change
-  the style, commit, and then change the code, or vice-versa.
-- Set editors to replace tabs with spaces and do not trim trailing spaces. 
Tabs confound the version
-  control alerts. Trimming trailing spaces creates unnecessary changes.
-- Specify imported classes (do not use _.*_).
-- Write all if/else statements as full blocks with each clause within braces, 
unless the entire statement fits
-  on the same line.
-- Use `FIXME:` and `TODO:` tokens to mark follow up notes in code. You may also
-  include your Apache username and the date.
-- Omit `@author` tags.
-- `@since` to document changes between Struts versions, as in `@since Struts 
2.1.`
-- Wrap lines of code and JavaDoc at column 78. You can include a "comment 
rule" in the source to help with
-  this.
-- Please do your best to provide high-quality Javadocs for all source code 
elements. Package overviews
-  (aka "Developer Guides") are also encouraged.
-- When working on a bugfix, please first write a test case that proves the bug 
exists, and then use the test
-  to prove the bug is fixed. =:0)
-- When working on an enhancement, please feel free to use test-driven design 
and write the test first `<head-slap/>`
-- As files are updated from year to year, the copyright on each file should be 
extended to include the current
-  year. *You do not need to change the copyright year unless you change the 
file.*  Every source file should
-  include the ASF copyright notice and current Apache License and copyright.
-- Provide high-level API compatibility for any changes made within the same 
major release series (#.x.x).
-  Changes which adversely affect compatibility should be slotted for the next 
major release series (++#.x.x).
-- Our favorite books about programming are
-  [Design 
Patterns](http://www.amazon.com/exec/obidos/ISBN=0201633612/apachesoftwar-20/),
-  
[Refactoring](http://www.amazon.com/exec/obidos/ISBN=0201485672/apachesoftwar-20/),
-  and [Code 
Complete](http://www.amazon.com/exec/obidos/ISBN=0735619670/apachesoftwar-20/)
-- Our favorite book about open source development is the
-  [The Cathedral and the 
Bazaar](http://www.amazon.com/exec/obidos/ISBN=1565927249/apachesoftwar-20/)
-- Our favorite science fiction author is
-  [Robert Heinlein](http://www.nitrosyncretic.com/rah/),
-  [TANSTAAFL](http://jargon.net/jargonfile/t/TANSTAAFL),
-  (Except on Friday, when we favor [Douglas 
Adams](http://news.bbc.co.uk/1/hi/uk/1326657.stm)).
+- If a serious flaw is found in a release candidate or a release, it may be 
withdrawn by a
+  majority vote of the PMC and removed from ASF distribution channels.
+
+## Before you start
+
+### Two lines mean two releases
+
+`main` is the 7.x line and `support/struts-6-x-x` is the 6.x line. Both are 
protected in
+`.asf.yaml` and both must be green before you start.
+
+| Line | Branch | Build check that must pass | JDK |
+|---|---|---|---|
+| 7.x | `main` | `Build and Test (JDK 17)` | 17 |
+| 6.x | `support/struts-6-x-x` | `Build and Test (8)` | 8 |
+
+A change that lands on both lines is **two releases** — each with its own tag, 
vote, site entry
+and announcement, not one release mentioned twice. They can be cut and voted 
in parallel, and
+usually are, but keep the version numbers independent: 6.11.0 and 7.3.0 
shipped on the same day
+and share nothing but a date.
+
+### Check the JDK before building anything
+
+The whole release is produced by whichever JDK happens to be active in your 
shell, and the line
+dictates which one that must be. Cutting 6.x on JDK 17 produces artifacts that 
will not run for
+the users that line exists for.
+
+```bash
+mvn -v    # reports the JDK Maven is actually using, not just $JAVA_HOME
+```
+
+{:.alert .alert-warning}
+If it reports the wrong version, stop and switch before going any further.
+
+### The version number is decided at release time
+
+The `-SNAPSHOT` in the pom is a placeholder, not a decision. Pick the number 
from the semantic
+versioning impact of what actually landed since the last tag, and state it 
before cutting — the
+tag is the first irreversible act of the release.
+
+The pom cannot tell you what the number is. Because releases are cut on a side 
branch, the root
+pom on `main` still read `7.2.2-SNAPSHOT` after 7.3.0 had shipped.
+
+### What you need access to
+
+- A committer account with your Apache and GitHub accounts linked in
+  [GitBox](https://gitbox.apache.org/setup/).
+- A code signing key published in
+  [`KEYS`](https://dist.apache.org/repos/dist/release/struts/KEYS) and in the 
ASF web of trust.
+- ASF credentials for `dist.apache.org` (Subversion) and for
+  [Nexus](https://repository.apache.org/).
+
+## The seven phases
+
+A release is seven phases with a gate between each. A phase is finished when 
its gate is
+verifiable by someone other than you: "I ran the command" is not a gate, "the 
URL resolves" is.
+
+| # | Phase | Gate before moving on |
+|---|---|---|
+| 1 | [Prepare](#phase-1--prepare) | Branch green, version decided, parent 
poms released |
+| 2 | [Cut](#phase-2--cut) | Tag pushed, artifacts in a **closed** Nexus 
staging repository |
+| 3 | [Stage](#phase-3--stage) | Assemblies in `dist/dev`, Version Notes page 
live, `[TEST]` mail sent |
+| 4 | [Vote](#phase-4--vote) | 72 hours elapsed, three binding `+1`, result 
mail sent |
+| 5 | [Promote](#phase-5--promote) | Nexus repository released, `dist/dev` → 
`dist/release`, 24 hour rsync waited |
+| 6 | [Publish](#phase-6--publish) | Site updated, GitHub release un-flagged, 
`[ANN]` mail delivered |
+| 7 | [Advisories](#phase-7--security-advisories) | Bulletins public, CVE 
records filled, advisory mails delivered |
+
+Phase 7 exists only when the release carries a security fix, and it is 
strictly the last thing
+that happens — see [Security advisories](#phase-7--security-advisories).
+
+## Phase 1 — Prepare
+
+Start from a clean, up-to-date checkout of the line you are releasing and 
confirm it builds.
+
+```bash
+git checkout main && git pull --ff-only
+mvn clean install -DskipAssembly
+```
+
+Then:
+
+- Decide the version number from its semantic versioning impact. Do not read 
it off the
+  `-SNAPSHOT`.
+- Confirm that `struts-master` and `struts-annotations` are released versions, 
not snapshots. The
+  root pom's `<parent>` must not point at a snapshot.
+- Review JIRA: every issue fixed since the last tag has a fix version set, and 
nothing unresolved
+  carries the version you are about to release.
+- Release the version in JIRA once the last issue is closed, and add the next 
version to the
+  roadmap.
+
+The BOM needs no version synchronisation. `bom/pom.xml` inherits the root 
version through its
+`<parent>` and declares its members as `${project.version}`.
+
+## Phase 2 — Cut
+
+### Cut from a release branch, not from the line branch
+
+```bash
+git checkout -b release/7.3.0-RC1 main    # or off support/struts-6-x-x for 
the 6.x line
+git push -u origin release/7.3.0-RC1
+```
+
+The two `[maven-release-plugin]` commits land on that branch and the line 
branch is never
+touched. A failed vote is then a deleted branch rather than a revert.
+
+### Prepare and perform
+
+```bash
+mvn release:prepare
+```
+
+No flags. `autoVersionSubmodules` is configured in the root pom, alongside the 
ASF parent's
+`useReleaseProfile=false`, `goals=deploy` and 
`releaseProfiles=apache-release`. If you find
+yourself passing `-D` to the release plugin, the setting belongs in the pom 
instead — a flag that
+has to be remembered is a flag that will be forgotten.
+
+{:.alert .alert-warning}
+At the SCM tag prompt, type `STRUTS_X_Y_Z`. The plugin's default is derived 
from the root
+artifactId and is wrong; every Struts tag in history uses the underscore form, 
and the GitHub
+release, the Version Notes and the website all assume it.
+
+For a [dry 
run](http://maven.apache.org/plugins/maven-release-plugin/usage.html) add
+`-DdryRun=true`, then `mvn release:clean` before the real run. If the command 
fails part way
+through, re-run it as is: `-Dresume` defaults to true and it picks up where it 
stopped.
+
+The result is two commits on the release branch — `[maven-release-plugin] 
prepare release
+STRUTS_X_Y_Z` and `[maven-release-plugin] prepare for next development 
iteration` — plus the tag.
+
+```bash
+mvn release:perform
+```
+
+`retryFailedDeploymentCount` is configured on `maven-deploy-plugin` in the 
root pom, not passed
+here. It has to be in the pom to work at all: `release:perform` forks a fresh 
Maven build, and
+that fork does not inherit `-D` properties from the outer invocation.
+
+If you need to run the deployment again, or from a different machine:
+
+```bash
+git checkout STRUTS_X_Y_Z
+mvn javadoc:javadoc deploy -DperformRelease=true -Papache-release
+```
+
+### Close the staging repository
+
+Log in to [Nexus](https://repository.apache.org/), then **Staging 
Repositories** → select the
+repository → **Close**.
+
+{:.alert .alert-warning}
+A successful `release:perform` leaves the repository *open*, and an open 
repository serves
+nothing under the staging group URL. Until it is closed, every link in the 
Version Notes resolves
+to nothing and no one can test the build.
+
+The gate is that the artifacts resolve under:
+
+```
+https://repository.apache.org/content/groups/staging/org/apache/struts/struts2-core/$VERSION/
+```
+
+The staging repository is keyed by user *and* public IP address. If your 
address changed mid
+release you will have two of them; check the dates and drop the stale one.
+
+## Phase 3 — Stage
+
+To make the build testable, the assemblies are moved out of Nexus into
+`https://dist.apache.org/repos/dist/dev/struts/$VERSION`. The steps are 
scripted in
+[`stage-assemblies.sh`](https://github.com/apache/struts/blob/main/.claude/skills/releasing-struts/scripts/stage-assemblies.sh);
+run it from a scratch directory, since it creates `./$VERSION` and a temporary 
Subversion working
+copy in the current directory.
+
+```bash
+cd "$(mktemp -d)"
+VERSION=7.3.0 /path/to/stage-assemblies.sh
+```
+
+It fetches the `zip`, `md5`, `sha1` and `asc` files from the closed staging 
repository, strips
+the `2-assembly` infix from their names, drops the `.pom` files and the legacy 
`md5`/`sha1`
+hashes, generates `.sha256` and `.sha512` locally, prints what it is about to 
publish, and then
+commits the directory to `dist/dev/struts`. In outline:
+
+```bash
+wget -erobots=off -nv -l 1 --accept=zip,md5,sha1,asc -r -nd -nH \
+  
https://repository.apache.org/content/groups/staging/org/apache/struts/struts2-assembly/$VERSION
+for f in *2-assembly*.zip*; do mv "$f" "$(echo "$f" | sed s/2-assembly//g)"; 
done
+rm -f struts2-assembly-*.pom* ./*.md5 ./*.sha1
+for f in *.zip; do shasum -a 256 "$f" > "$f.sha256"; shasum -a 512 "$f" > 
"$f.sha512"; done
+svn --no-auth-cache co --depth empty 
https://dist.apache.org/repos/dist/dev/struts/ struts-dev
+mv $VERSION struts-dev/ && cd struts-dev
+svn add --force ./
+svn --no-auth-cache commit -m "Updates test release $VERSION"
+```
+
+The gate is `https://dist.apache.org/repos/dist/dev/struts/$VERSION/`, holding 
**six** assemblies
+— `struts-$VERSION-all.zip`, `-apps.zip`, `-docs.zip`, `-lib.zip`, 
`-min-lib.zip` and `-src.zip`
+— each with an `.asc`, `.sha256` and `.sha512` beside it: 24 files, no `.md5`, 
no `.sha1`, no
+`.pom`. `KEYS` lives one level up, in `dist/release/struts/`.
+
+{:.alert .alert-warning}
+Count the files. The script stops on a step that fails, not on a download that 
quietly returns a
+subset, so a short upload can reach `dist/dev` looking healthy.
+
+The rest of this phase is paperwork:
+
+- Create the **Version Notes** page in the wiki for the new version, linking 
the previous notes in
+  the series, the JIRA issues fixed, and the staging repository, and link it 
from the
+  [Migration 
Guide](https://cwiki.apache.org/confluence/display/WW/Migration+Guide).
+- Create the **GitHub release** for the tag, flagged as a **prerelease**.
+- Send a `[TEST]` mail to `[email protected]` and 
`[email protected]` announcing that the
+  build is available, and give people time to test the actual bits.
+
+## Phase 4 — Vote
+
+Post a release/quality vote to the dev list and only the dev list.
+
+```
+To: [email protected]
+Bcc: [email protected]
+```
+
+Never `user@`. `private@` is copied so that binding voters see the thread.
+
+The vote runs for a **minimum of 72 hours** and needs **three binding `+1`** 
votes; PMC members'
+votes are the binding ones. Close the vote with a result mail on the same 
thread.
+
+If the vote fails, delete the release branch and start again from phase 1 with 
a new version
+number. Nothing that has been published so far is promoted.
+
+## Phase 5 — Promote
+
+Move the assemblies from `dist/dev` to `dist/release`. This is the point at 
which they start
+replicating to the mirrors. The step is scripted in
+[`promote-dist.sh`](https://github.com/apache/struts/blob/main/.claude/skills/releasing-struts/scripts/promote-dist.sh):
+
+```bash
+svn mv https://dist.apache.org/repos/dist/dev/struts/$VERSION/ \
+       https://dist.apache.org/repos/dist/release/struts/ \
+       -m "Release Struts $VERSION"
+```
+
+Then log in to [Nexus](https://repository.apache.org/) again and **release** 
the staging
+repository, which replicates the artifacts to Maven Central. See
+[Releasing a Maven-based 
project](http://maven.apache.org/developers/release/apache-release.html)
+for further details.
+
+Old releases may be removed from `dist/release/struts/` to keep the mirror set 
small; everything
+removed stays available from 
[archive.apache.org](https://archive.apache.org/dist/struts/).
+Decide deliberately which versions to keep — in practice several supported 
versions from both
+lines are kept — and do not prune on autopilot.
+
+```bash
+svn del https://dist.apache.org/repos/dist/release/struts/$OLD_VERSION/ -m 
"Removing old release"
+```
+
+{:.alert .alert-danger}
+Wait **24 hours** after the move before anything in phase 6. This is the ASF 
mirroring
+requirement, and announcing into an unmirrored release sends everyone to a 404.
+
+## Phase 6 — Publish
+
+### Update the website
+
+The site is [apache/struts-site](https://github.com/apache/struts-site) and 
publishing is the
+merge — there is no separate deploy step. Open a pull request against `main`; 
it is staged
+automatically at [struts.staged.apache.org](https://struts.staged.apache.org/) 
for review.
+
+`_config.yml` — these move together:
+
+```yaml
+current_version: 7.3.0
+current_version_short: 730
+prev_version: 6.11.0
+prev_version_short: 6110
+release_date: 1 August 2026
+prev_release_date: 1 August 2026
+release_date_short: 20260801
+prev_release_date_short: 20260801-6110
+```
+
+`release_date` is the **tag** date, not the announcement date: 7.2.1 was 
tagged on 15 June and
+announced on 30 June, and the site says 15 June. The `*_date_short` values are 
the anchors in
+`announce-YYYY.md`; when two releases share a tag date, disambiguate the 
second one (as
+`20260801-6110` above) so that each home page box links to its own entry.
+
+Then:
+
+- `source/announce-YYYY.md` — a new `####` entry at the top, newest first, 
with its
+  `{% raw %}{#aYYYYMMDD}{% endraw %}` anchor.
+- `source/releases.md` — the release table, and move the superseded version 
into
+  **Prior Releases**. This one is easy to miss; a site update without it is 
incomplete.
+- `source/index.html` — the GA boxes read their values from `_config.yml`; the 
security boxes are
+  hand-edited.
+- `source/dtds/` — only if a new DTD shipped.
+
+`source/download.cgi` and `source/download.md` need no per-release edit: the 
first is a wrapper
+around `mirrors.cgi`, and the second interpolates its versions from 
`_config.yml`.
+
+### Un-flag the GitHub release
+
+Remove the prerelease flag from the GitHub release created in phase 3. Title 
`Struts X.Y.Z`, tag
+`STRUTS_X_Y_Z`.
+
+{:.alert .alert-warning}
+The release must stay flagged as a prerelease for the whole of the vote. 
Un-flagging it early
+means voting on an artifact the world already treats as final.
+
+### Announce it
+
+```
+To: [email protected]
+Cc: [email protected], [email protected]
+```
+
+`dev@` is not on it — the list already saw the `[TEST]` mail and the vote.
+
+{:.alert .alert-danger}
+The announcement must be **plain text** and sent from your `@apache.org` 
identity.
+`[email protected]` rejects any message carrying a `text/html` part, and
+`[email protected]` rejects anything not sent from an 
`@apache.org` address. One
+list accepting the mail is not evidence that the format was right.
+
+The body carries the General Availability boilerplate, a link to the Version 
Notes, a link to the
+Migration Guide for a new major line, the minimum JDK and specification 
requirements for that
+line, and the [download page](download.cgi).
+
+## Phase 7 — Security advisories
+
+This phase exists only when the release carries a security fix, and it happens 
**after** phase 6.
+The bulletin itself is usually written when the report is triaged, which may 
be months before a
+release carries the fix.
+
+The ordering is not negotiable:
+
+```
+release GA  →  bulletin published  →  advisory mails  →  CVE record submitted
+```
+
+A bulletin published before the fixed artifact is downloadable tells attackers 
what to look for
+and gives operators nothing to do about it.
+
+{:.alert .alert-danger}
+Nothing about an unpublished advisory goes into the release paperwork — not 
the Version Notes,
+not the `[TEST]` mail, not the `[VOTE]`, not the commit messages, not the site 
entry. Neutral
+tickets are what let the embargo survive a public release process.
+
+A release containing *only* embargoed fixes is self-disclosing: the difference 
between the two
+tags is the vulnerability, whatever the commit messages say. That is a reason 
to bundle such
+fixes with unrelated work, or to publish the bulletins together with the 
release — not a reason
+to pretend otherwise.
+
+The CVE record goes `RESERVED → DRAFT → READY`, and `READY` is the last state 
the PMC sets. ASF
+Security submits it to the CVE Program and sets it `PUBLIC`, so `cve.org` 
links return 404 until
+they do. That is expected and is not a reason to delay the bulletin or the 
mails.
+
+See [Security bulletins](security/) for how bulletins are written and 
published, and
+[Reporting security issues](security) for how reports reach us in the first 
place.
+
+## After the release
+
+- Add a site announcement entry for any security advisory, in the same form as 
the GA one.
+- Check the [NVD](https://nvd.nist.gov/) entry once a CVE goes public. The 
affected ranges have
+  been wrong before; the fix is an email to `[email protected]` citing the CVE 
record.
+- Answer any coordinator who is holding an advisory in their existing thread, 
once ours is live.
+- Update the Version Notes page if the vote forced a re-cut.
+
+## Red flags
+
+Stop if any of these is about to happen:
+
+- Cutting a tag before the version number has been stated and agreed.
+- Inferring the release version from the `-SNAPSHOT` in the pom.
+- A `[VOTE]` opened on a staging repository that is not closed, or on a link 
that 404s.
+- Announcing before the 24 hour mirror wait.
+- Any severity, CVE, `S2-XXX` or bulletin link appearing in release paperwork.
+- A bulletin published before the fixed release is downloadable.
+- One release "covering" both maintenance lines.
 
 Next: [PMC Charter](bylaws)

Reply via email to