Skip to content

Close the v2 re-audit's configs findings - #56

Merged
ahegyes merged 5 commits into
trunkfrom
fix/reaudit-followups
Oct 29, 2026
Merged

ahegyes merged 5 commits into
trunkfrom
fix/reaudit-followups

Conversation

@ahegyes

@ahegyes ahegyes commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Summary

Five fixes from the v2 re-audit:

  • the release let a plugin ship with a Requires PHP below its own composer.json floor, and it packed phpunit.dist.xml;

  • four release steps and the PHPStan path discovery had no test;

  • the Node baselines assume TypeScript 6 but declared no typescript peer;

  • the README stated floors as numbers that its manifests own.

  • Release floor: the header check reads the project's own composer.json beside the shipped packages, so Requires PHP must cover the plugin's own floor too. docs/workflows.md says so.

  • phpunit.dist.xml: the baseline .distignore and the archive's forbidden-entry check match phpunit*.xml*, so phpunit.dist.xml, PHPUnit's default name, stays out of the zip.

  • Release-gate tests: new rows run four steps that had none:

    • "Assert scoped packages bundled", with a complete archive, a missing autoloader or package, and a build whose scoping never ran;
    • "Verify required workflows passed", with every, one or no required workflow among the push runs, a malformed list and an unavailable API;
    • the release-notes extraction, with dated, bracketed and absent sections, a heading whose dots are not wildcards, and no changelog;
    • phpstan.dist.neon.php's path discovery, over a plugin-shaped directory.
  • TypeScript peer: typescript >=6.0.0 joins the tool peers. node/tsconfig.base.json carries only deltas from TypeScript 6's strict defaults, so TypeScript 5 silently turned strict mode off. The lock moves only its root entry.

  • Docs and comments: the README and AGENTS.md name each floor by the file and key that hold it, and six workflow comments each state their why in one sentence.

Workflows +12 −29 (4 files), tests +193 (2 files), docs +6 −6 (3 files), .distignore +1 −1, npm manifest and lock +4 −3.

Type of change

  • PHP source (Composer scripts, php-scoper config)
  • Reusable workflow (.github/workflows/reusable-*.yml)
  • PHPCS / PHPStan ruleset (php/quality-assurance/)
  • Node config (eslint, stylelint, playwright, tsconfig)
  • Documentation
  • Other

Checklist

  • Tests added or updated (PHPUnit suites under tests/Unit/):
    • ReleaseWorkflowTest: a root composer.json requiring PHP 8.5 against Requires PHP: 7.4, and an archive holding phpunit.dist.xml, both passed the old steps and fail the new ones;
    • the scoped-package, provenance and release-notes rows pin what those steps accept and refuse;
    • PhpstanConfigTest: path discovery adds the conventional root files and source directories and scans vendor-prefixed/.
  • composer test passes locally:
    • composer quality-check: PHPCS on both profiles, PHPStan and 149 tests;
    • npm run lint:scripts, npm run lint:config, actionlint and zizmor pass.
  • If this changes a reusable workflow's inputs/outputs, docs/workflows.md is updated to reflect the new contract. There are no input or output changes; the release's floor rule in docs/workflows.md names the project's own composer.json.
  • If this changes a ruleset, downstream consumer behavior is considered (no ruleset changes)

Breaking changes for downstream consumers

  • Release floor: a release whose entry file's Requires PHP is below the project's own require.php now fails its build, because the header understated the plugin's floor.
  • TypeScript peer: a consumer that installs TypeScript 5 beside the Node baselines now has an unmet typescript >=6.0.0 peer, which npm reports as a conflict.

Not in this PR: the release's archive tools (WP-CLI, dist-archive-command and the i18n command behind wp i18n make-pot) still install unlocked. Locking them needs a decision on where the lock lives, because a consumer of reusable-release.yml need not install this package and a reusable workflow cannot read its own commit.

The release compared the entry's Requires PHP with the require.php of
the production packages in vendor/ and the scoped ones in
vendor-prefixed/, but never with the project's own composer.json. A
plugin that raised its own floor for its own syntax and forgot its
header shipped, and with Composer's platform check off the header is
the only gate, so sites between the two passed it and failed to parse
the plugin.

The baseline .distignore and the archive's forbidden-entry check both
matched phpunit.xml* only, which misses phpunit.dist.xml, PHPUnit's
default name.

The header check now reads the project's composer.json beside the
shipped packages, and both exclusions match phpunit*.xml*. A row whose
root alone requires the higher floor and a phpunit.dist.xml archive row
fail without the change.

Assisted-by: Claude Code:claude-opus-5-5
AGENTS.md says the unit tests run the release's assertion steps, but
"Assert scoped packages bundled", "Verify required workflows passed",
the release-notes extraction and the opt-in phpstan.dist.neon.php path
discovery had no row, so a change to their logic would pass. They fail
closed, but nothing pinned what they accept.

Rows now run each step: a complete scoped archive, a missing autoloader
or package and a build whose scoping never ran; every, one or no
required workflow among the push runs, a malformed list and an
unavailable API; a dated, a bracketed and an absent changelog section,
a heading whose dots are not wildcards and no changelog at all; and the
path discovery over a plugin-shaped directory.

Assisted-by: Claude Code:claude-opus-5-5
node/tsconfig.base.json carries only deltas from TypeScript 6's
defaults, strict mode among them, but the package declared no
typescript peer, so a consumer resolving TypeScript 5 turned strict
off without a word.

The package lists typescript >=6.0.0 beside its other tool peers, the
major it is tested against (6.0.3), and the README names it.

Assisted-by: Claude Code:claude-opus-5-5
The README's Requirements gave PHP 8.5, Node 26, npm 11 and WordPress
7.1 as numbers that composer.json, package.json and the PHPCS and
PHPStan profiles own, and AGENTS.md required the copies, so a floor
change had to edit prose in step with the manifests. The style guide
allows no number another file owns, as the framework's READMEs follow.

The README names each file and key that holds a floor, and AGENTS.md
says so instead.

Assisted-by: Claude Code:claude-opus-5-5
Six comments in the workflows and dependabot.yml ran to several
sentences, one with an all-caps MUST, against the rule that an inline
comment states a non-obvious why in one sentence.

Each now states its why once.

Assisted-by: Claude Code:claude-opus-5-5
@ahegyes ahegyes changed the title Fix/reaudit followups Close the v2 re-audit's configs findings Oct 29, 2026
@ahegyes
ahegyes merged commit fbd4c2c into trunk Oct 29, 2026
29 checks passed
@ahegyes
ahegyes deleted the fix/reaudit-followups branch October 29, 2026 14:32
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