Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- fix: remove the unnecessary `src` argument from the Rector command in `composer.json`.
- feat: prepare Foxy `0.3` for PHP `8.3`, faster execution, safer fallbacks, updated tooling, and clearer docs.
- fix: preserve plugin self-updates and clarify framework-agnostic Composer application support.
- feat!: require Bun `^1.4.0`, npm `^12.0.2`, pnpm `^11.23.0`, or Yarn `^4.18.0` and remove legacy manager support.
- feat!: require Bun `^1.4.0`, npm `>=10.9.8`, pnpm `^11.23.0`, or Yarn `^4.18.0` and remove legacy manager support.
- fix: run manager commands in the configured root directory without changing the PHP working directory, and prevent manager probes and npm dependency cleanup when manager execution is disabled.
- feat!: add secure frontend audits with CVE reporting, CI formats, and strict npm, pnpm, Yarn, and Bun validation.

## 0.2.0 January 24, 2026

Expand Down
29 changes: 22 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@

- PHP 8.3 or later.
- Composer 2.10.2 or later.
- One supported frontend manager when manager execution is enabled:
- One supported frontend manager for automatic manager execution or explicit security audits:
- Bun `^1.4.0`.
- npm `^12.0.2` with Node.js `^22.22.2 || ^24.15.0 || >=26.0.0`.
- npm `>=10.9.8` with a Node.js version supported by the selected npm release.
- pnpm `^11.23.0` with Node.js `>=22.13.0`.
- Yarn `^4.18.0` with Node.js `>=18.12.0`; use a Node.js release that still receives security updates.

Expand Down Expand Up @@ -71,12 +71,27 @@ Selecting a manager explicitly is recommended for reproducible local and CI beha
}
```

Valid manager values are `bun`, `npm`, `pnpm`, and `yarn`. When manager execution is enabled and `manager` is omitted,
Foxy first looks for one recognized native lockfile and then checks available executables. Configure the manager
explicitly when the project contains lockfiles from more than one manager.
Valid manager values are `bun`, `npm`, `pnpm`, and `yarn`. When automatic manager execution is enabled and `manager` is
omitted, Foxy first looks for one recognized native lockfile and then checks available executables. Configure the
manager explicitly when the project contains lockfiles from more than one manager.

When `run-asset-manager` is `false`, Foxy does not require or probe a manager binary. Automatic selection uses the
single recognized lockfile when present, or npm as the manifest adapter when no lockfile exists.
During automatic Composer processing, `run-asset-manager=false` prevents Foxy from requiring or probing a manager
binary. Automatic selection uses the single recognized lockfile when present, or npm as the manifest adapter when no
lockfile exists. An explicit `composer foxy:audit` still validates and runs the selected manager.

## Frontend security audit

Audit the exact frontend dependency graph recorded by the selected manager's lockfile:

```bash
composer foxy:audit
composer foxy:audit --format=summary --no-dev --audit-level=high
```

Foxy normalizes the current npm, pnpm, Yarn, and Bun audit reports and identifies the affected package, advisory,
severity, vulnerable range, and CVE identifiers when GitHub maps the advisory to a CVE. The command returns `0` when no
advisory meets the configured threshold, `1` when at least one does, and `2` when the audit cannot be completed
reliably. See the [usage guide](docs/usage.md#security-auditing) for formats and CI examples.

## Quick start

Expand Down
25 changes: 15 additions & 10 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ Before updating, ensure the environment provides:

- PHP 8.3 or later.
- Composer 2.10.2 or later.
- One supported frontend manager when manager execution is enabled: Bun `^1.4.0`, npm `^12.0.2`, pnpm `^11.23.0`, or Yarn `^4.18.0`.
- For npm, Node.js `^22.22.2 || ^24.15.0 || >=26.0.0`.
- One supported frontend manager for automatic manager execution or explicit security audits: Bun `^1.4.0`, npm `>=10.9.8`, pnpm `^11.23.0`, or Yarn `^4.18.0`.
- For npm, use a Node.js version supported by the selected npm release.
- For pnpm, Node.js `>=22.13.0`.
- For Yarn, Node.js `>=18.12.0` on a release that still receives security updates.

Expand Down Expand Up @@ -64,19 +64,18 @@ configure the manager and commit its native lockfile:

Remove stale lockfiles from other managers before the first Composer operation with Foxy 0.3.

#### npm 12 migration
#### npm migration

Upgrade Node.js to a release accepted by npm 12 first, then install the latest npm 12 release and regenerate the
installation state:
Ensure npm is at least 10.9.8 and regenerate the installation state:

```bash
npm install --global npm@12
npm --version
npm install
```

The reported npm version must satisfy `^12.0.2`. Review npm 12 configuration changes against the
[npm 12 documentation](https://docs.npmjs.com/cli/v12/) and commit any `package-lock.json` changes.
The reported npm version must satisfy `>=10.9.8`. npm 10.9.8 requires Node.js `^18.17.0 || >=20.5.0`; later npm
releases may require a newer Node.js version. Review the [npm documentation](https://docs.npmjs.com/cli/) for the
selected release and commit any `package-lock.json` changes.

#### pnpm 11 migration

Expand Down Expand Up @@ -132,7 +131,11 @@ The [Yarn migration guide](https://yarnpkg.com/migration/guide) documents the co

Custom `AssetManagerInterface` implementations must add `getVersionConstraint(): string` and return their hard
supported version range as a Composer constraint. Remove implementations and calls of the obsolete
`isValidForUpdate()` method.
`isValidForUpdate()` method. Custom `AbstractAssetManager` subclasses must also implement
`getAuditCommand(bool $noDev): string`. Foxy currently normalizes only the report schemas and manager names of its four
built-in managers; arbitrary custom managers are not supported by `composer foxy:audit`. Direct `AssetManagerInterface`
implementations that do not implement Foxy's auditable manager contract remain usable for asset solving, but the audit
command reports that they cannot be audited reliably.

`AbstractAssetManager` subclasses inherit the simplified update eligibility based on installation state and the
`setUpdatable()` flag, concrete-version enforcement before every manager command, and version detection in the
Expand Down Expand Up @@ -187,4 +190,6 @@ when necessary, revert the root manifest after a failed operation.

Setting `enabled=false` now bypasses manager discovery, fallback snapshots, package merging, and manager execution.
Setting `run-asset-manager=false` retains package merging but skips manager binary probing, version validation,
execution, and npm cleanup of existing `node_modules/@composer-asset/*` installations.
execution, and npm cleanup of existing `node_modules/@composer-asset/*` installations. The new explicit
`composer foxy:audit` command still validates and invokes the selected manager in this mode; it never installs, updates,
or repairs dependencies.
10 changes: 8 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,14 @@
"scripts": {
"check-dependencies": "./vendor/bin/composer-require-checker check",
"ecs": "./vendor/bin/ecs --fix",
"mutation": "./vendor/bin/infection --threads=4 --min-msi=100 --min-covered-msi=100",
"mutation-static": "./vendor/bin/infection --threads=4 --min-msi=100 --min-covered-msi=100 --static-analysis-tool=phpstan --static-analysis-tool-options='--memory-limit=-1 --debug'",
"mutation": [
"Composer\\Config::disableProcessTimeout",
"@php -d memory_limit=-1 ./vendor/bin/infection --threads=4 --with-uncovered --min-msi=100 --min-covered-msi=100"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
],
"mutation-static": [
"Composer\\Config::disableProcessTimeout",
"@php -d memory_limit=-1 ./vendor/bin/infection --threads=4 --with-uncovered --min-msi=100 --min-covered-msi=100 --static-analysis-tool=phpstan --static-analysis-tool-options='--memory-limit=-1'"
],
"rector": "./vendor/bin/rector process",
"static": "./vendor/bin/phpstan --memory-limit=-1",
"sync-metadata": [
Expand Down
31 changes: 23 additions & 8 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ manager-prefixed environment variable should contain the scalar value for the ac
| `manager-install-options` | string or map | Empty | Appends options only to install commands. |
| `manager-update-options` | string or map | Empty | Appends options only to update commands. |
| `manager-timeout` | integer or map | No practical limit | Sets the manager process timeout in seconds. |
| `run-asset-manager` | boolean | `true` | Controls manager probing and execution while retaining package merging. |
| `run-asset-manager` | boolean | `true` | Controls automatic manager probing and install or update execution. |
| `fallback-asset` | boolean | `true` | Restores `package.json` after asset processing fails. |
| `fallback-composer` | boolean | `true` | Restores Composer lock and vendor state after asset solving fails. |
| `composer-asset-dir` | string or `null` | `<vendor-dir>/php-forge/composer-asset/` | Sets the mock package directory. |
Expand Down Expand Up @@ -106,14 +106,16 @@ When manager execution is enabled, Foxy validates the selected manager against i
| Manager | Built-in constraint |
| ------- | ------------------- |
| Bun | `^1.4.0` |
| npm | `^12.0.2` |
| npm | `>=10.9.8` |
| pnpm | `^11.23.0` |
| Yarn | `^4.18.0` |

The `manager-version` option adds another Composer constraint that is evaluated together with the built-in constraint.
It can narrow the accepted versions for a project, but it cannot replace or widen Foxy's supported range.
Foxy treats the reported value as one concrete release and validates it from `root-package-json-dir` before every
manager command. When `run-asset-manager` is `false`, Foxy neither probes, executes, nor validates the manager binary.
manager command. During automatic Composer processing, `run-asset-manager=false` prevents probing, execution, and
validation of the manager binary. An explicit `composer foxy:audit` remains an exception because it is a direct user
request.

Narrow the npm constraint for one project:

Expand All @@ -122,7 +124,7 @@ Narrow the npm constraint for one project:
"config": {
"foxy": {
"manager": "npm",
"manager-version": "~12.0.2"
"manager-version": "~10.9.8"
}
}
}
Expand All @@ -135,16 +137,16 @@ Manager-prefixed options may also use a map when a shared configuration supports
"config": {
"foxy": {
"manager-version": {
"npm": "~12.0.2",
"npm": "~10.9.8",
"pnpm": "~11.23.0"
}
}
}
}
```

For example, configuring npm with `>=11.0.0` does not enable npm 11 because the built-in `^12.0.2` constraint remains
in force. Remove `manager-version` to accept the complete built-in range for the selected manager.
For example, configuring npm with `<10.9.8` does not enable an older release because the built-in `>=10.9.8`
constraint remains in force. Remove `manager-version` to accept the complete built-in range for the selected manager.

## Manager executable and options

Expand Down Expand Up @@ -178,6 +180,18 @@ Use the three manager option settings only when native manager configuration fil

These values are appended to an external command. Treat project, global, and environment configuration as trusted
input. Prefer native files such as `.npmrc`, `.yarnrc.yml`, `pnpm-workspace.yaml`, or `bunfig.toml` where appropriate.
They apply to install and update operations only. `foxy:audit` owns its machine-output, advisory-filter, and
dependency-scope flags and does not inherit these options. It does honor `manager-bin`, `manager-version`,
`manager-timeout`, and `root-package-json-dir`.

Where the native manager supports an explicit override, Foxy neutralizes inherited settings that could exclude
dependencies or advisories. Bun 1.4 cannot reset every inherited dependency-scope setting without also discarding
registry configuration. Foxy therefore rejects a Bun audit when a loaded `.npmrc` or `bunfig.toml` excludes a dependency
type required by the requested audit. Remove the restrictive setting, or use `--no-dev` when the only restriction is the
development dependency graph. Audit preflight also requires UTF-8 configuration and canonical `[install]` table syntax;
inline or array install tables, escaped keys or omit values, and multiline values inside `[install]` are rejected rather
Comment thread
coderabbitai[bot] marked this conversation as resolved.
than interpreted heuristically. The preflight rejects restrictive declarations even when a later `include` or
higher-precedence file would override them.

## Manager timeout

Expand Down Expand Up @@ -209,7 +223,8 @@ Disable manager binary probing and execution while continuing to update `package

In this manifest-only mode, Foxy does not probe manager binaries, run install or update commands, or remove existing
`node_modules/@composer-asset/*` installations during npm reconciliation. Generated Composer asset manifests and the
root `package.json` are still updated.
root `package.json` are still updated. An explicit `composer foxy:audit` remains available and validates and runs the
selected manager because it represents a direct user request.

## Fallbacks

Expand Down
12 changes: 12 additions & 0 deletions docs/faqs.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ Multiple recognized lockfiles require explicit selection in either mode.

Explicit selection and a committed native lockfile are recommended for CI.

## How can frontend dependencies be checked for known CVEs?
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Run `composer foxy:audit`. Foxy audits the dependency graph from the selected manager's native lockfile. The default
table, plain, and JSON formats identify the affected package, advisory, severity, vulnerable range, and available CVE
identifiers. Use `--format=summary` for compact counts in CI or `--format=json` for a versioned machine-readable
document.

The native registry response commonly contains a GHSA but no CVE. Foxy resolves that relationship through GitHub's
public advisory API unless `--no-cve` or `--format=summary` is supplied. A lookup failure is shown as unavailable
without hiding the native security finding. See [Security auditing](usage.md#security-auditing) for options and exit
statuses.

## Why is a dependency's package.json not detected?

Check the following:
Expand Down
11 changes: 6 additions & 5 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ package version only when the embedded package does not declare its own version.
| PHP | 8.3 or later |
| Composer | 2.10.2 or later |
| Bun | `^1.4.0` |
| npm | `^12.0.2`; Node.js `^22.22.2 \|\| ^24.15.0 \|\| >=26.0.0` |
| npm | `>=10.9.8`; use a Node.js version supported by the selected npm release |
| pnpm | `^11.23.0`; Node.js `>=22.13.0` |
| Yarn | `^4.18.0`; Node.js `>=18.12.0` on a release that still receives security fixes |
| Git | Required only for Git-based dependencies |

The frontend manager requirements apply only when manager execution is enabled. Manifest-only mode does not require a
manager binary.
The frontend manager requirements apply to automatic manager execution and explicit security audits. Manifest-only
Composer processing does not require a manager binary, but `composer foxy:audit` does.

## Installation

Expand All @@ -47,8 +47,9 @@ Set `config.foxy.manager` to `bun`, `npm`, `pnpm`, or `yarn` when reproducible m
manager execution is enabled and the option is omitted, Foxy looks for one recognized native lockfile and then for an
available manager executable. Multiple recognized lockfiles require explicit selection.

When `run-asset-manager` is `false`, Foxy selects from a single lockfile or uses npm as the manifest adapter without
probing executables.
During automatic Composer processing, `run-asset-manager=false` makes Foxy select from a single lockfile or use npm as
the manifest adapter without probing executables. An explicit `composer foxy:audit` still probes and runs the selected
manager.

Commit the selected manager's native lockfile and use the same explicit manager in local development and CI.

Expand Down
Loading
Loading