Skip to content

fix: parity-hardening (bounded retry + previous-tag floor/history)#2

Merged
chhoumann merged 1 commit into
mainfrom
fix/parity-hardening
Jul 11, 2026
Merged

fix: parity-hardening (bounded retry + previous-tag floor/history)#2
chhoumann merged 1 commit into
mainfrom
fix/parity-hardening

Conversation

@chhoumann

Copy link
Copy Markdown
Owner

Parity-hardening for the shared release pipeline

Closes two defense-in-depth gaps the PodNotes parity audit (chhoumann/PodNotes#289)
found in the shared reusables, before the remaining three repos migrate.

1. Bounded retry around read-only forensic API calls

A transient 5xx from the GitHub API must not abandon a release the maintainer has
already merged. Added a small retryRead(thunk) helper (up to four attempts, only
on HTTP 5xx, linear backoff) and wrapped the read-only calls in release-validate
(the merge-time forensics) and release.yml's resolve job. Writes - the
recovery-branch createRef and the createWorkflowDispatch - are deliberately
NOT retried.

2. Previous-tag minAppVersion floor + full-history equality

minAppVersion and versions.json only change in lockstep with a release, so both
invariants are really about previous-tag vs base:

  • Floor: the compatibility minAppVersion may only rise, never drop, from the
    previous release to the base (and both must be stable semver).
  • History equality: versions.json is append-only and only a release PR edits
    it, so between two releases it must be byte-identical.

Both live in release-contract.mjs as validatePreviousTagHistory (new
validate-previous-tag CLI command) with unit tests, plus a stable-semver +
no-decrease floor in validateVersionFiles. Enforced at both gates: the release
build job (extracts the previous tag's manifest.json + versions.json and runs
the command; fetch-tags: true guarantees the tag is present) and inline in
release-validate at merge time.

Note (no action)

The merge-subject (#PR) suffix becoming mandatory is accepted as
stricter-not-weaker, per the audit.

Validation

  • pnpm test: 43/43 (was 38; +5 covering the floor and previous-tag checks, npm+pnpm).
  • CLI smoke test of validate-previous-tag (happy path, lowered floor, rewritten history).
  • actionlint clean on all workflows; pyyaml parses everything; no em-dashes.

- bounded 5xx retry around read-only forensic API calls in validate + resolve
- previous-tag minAppVersion floor (must not decrease) and versions.json
  full-history equality, in release-contract.mjs (validate-previous-tag) with
  tests, wired into the release build job and inline into release-validate
@chhoumann chhoumann merged commit 6289654 into main Jul 11, 2026
@chhoumann chhoumann deleted the fix/parity-hardening branch July 11, 2026 02:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 70b91caa07

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +379 to +383
const previousMinAppVersion = assertMinAppVersion(
previousManifest.minAppVersion,
"previous tag",
);
const baseMinAppVersion = assertMinAppVersion(baseManifest.minAppVersion, "base");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate previous tag metadata before trusting its floor

On the release.yml build path this CLI is the only previous-tag history check, but it trusts previousManifest.minAppVersion without first verifying that the previous tag's own metadata is synchronized, e.g. that previousVersions[previousManifest.version] matches it. If the previous tag is moved or otherwise points at a commit where manifest.json has a lowered floor while versions.json is unchanged, the history equality below still passes and the no-decrease comparison is made against the tampered lower value; the supported manual workflow_dispatch recovery path for release.yml does not run the inline release-validate metadata check. Validate the previous tag's version/history mapping before using its floor.

Useful? React with 👍 / 👎.

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