Skip to content

Latest commit

 

History

History
248 lines (189 loc) · 10.5 KB

usage.md

File metadata and controls

248 lines (189 loc) · 10.5 KB

Usage

Application setup

Authorize and require the plugin in the application:

{
  "require": {
    "php-forge/foxy": "^0.4"
  },
  "config": {
    "allow-plugins": {
      "php-forge/foxy": true
    },
    "foxy": {
      "manager": "npm"
    }
  }
}

The project may provide its own frontend dependencies in package.json:

{
  "private": true,
  "dependencies": {
    "@foo/bar": "^1.2.0"
  }
}

During Composer install and update operations, Foxy merges eligible Composer package assets into this file and runs the selected frontend manager. Existing non-Foxy dependencies are preserved. With "manager": "native", Foxy installs the merged file itself and writes foxy.lock; see Native manager.

Security auditing

Run an explicit frontend dependency audit from Composer:

composer foxy:audit

The command requires the selected manager's own lockfile, validates the manager version, and asks the manager for a security report. It reads the lockfile and does not run an install, update, fix, or fallback. Foxy supports npm audit report version 2 starting with npm 10.9.8, the current report schemas emitted by pnpm 11, Yarn 4, and Bun 1.4, and the npm registry's bulk advisories document read by the native manager; legacy report formats are rejected instead of being interpreted heuristically.

With the native manager, composer foxy:audit reads foxy.lock and asks the configured registry-url for advisories in one request to npm's bulk advisories endpoint (POST <registry-url>/-/npm/v1/security/advisories/bulk), sending every locked registry package with its version; local file: packages are not sent, and a lock without registry packages is clean without a request. --no-dev is rejected with status 2 because the native manager installs development dependencies together with the others. A registry that does not implement the endpoint fails the audit with status 2.

Deno does not provide a machine-readable report. Foxy runs deno audit --level=low with NO_COLOR=1 against deno.lock and parses its text report strictly. The parser is validated against Deno 2.9.7 and returns status 2 when the report layout is not recognized instead of guessing. Deno has no configuration setting that filters audit results, and Foxy does not forward manager options to the audit command.

Foxy reports every advisory returned by the manager. --audit-level controls only the CI exit threshold:

composer foxy:audit --audit-level=high

Valid levels are low, moderate, high, and critical; the default is low. Use --no-dev to audit only the production dependency graph:

composer foxy:audit --no-dev

For npm workspace roots, Foxy explicitly includes every workspace and the root package so ambient npm workspace selection cannot silently narrow the audited lock graph.

deno audit cannot exclude development dependencies, so a Deno audit with --no-dev returns status 2. Run the Deno audit without --no-dev to cover the complete dependency graph.

Foxy also overrides pnpm and Yarn settings that could silently filter the requested dependency graph or known advisories. Bun 1.4 cannot safely reset every inherited scope setting while retaining project registry and authentication configuration. A Bun audit therefore returns status 2 when a loaded .npmrc or bunfig.toml excludes a dependency type that the requested audit must cover. Development-only restrictions are accepted with --no-dev; optional and peer dependency restrictions are not. Bun configuration must be UTF-8 and use canonical [install] table syntax with single-line values so the preflight can verify it without heuristics. Restrictive declarations are rejected even when another setting would override them.

Audit output formats

Select table, plain, json, or summary with --format or -f:

composer foxy:audit --format=table
composer foxy:audit --format=plain
composer foxy:audit --format=json
composer foxy:audit --format=summary

The default table identifies the package, severity, advisory ID, CVE, vulnerable range, and advisory title. The JSON document has schema_version: 1 and is suitable for CI artifacts. Diagnostic and CVE lookup warnings are written to standard error so JSON on standard output remains valid.

The npm registry's audit data normally identifies advisories by a numeric ID and GHSA rather than a CVE. Unless --no-cve or --format=summary is used, Foxy resolves each unique public GHSA once through the GitHub global security advisories API. The lookups run concurrently through Composer's HTTP downloader, at most 12 at once by default; the COMPOSER_MAX_PARALLEL_HTTP environment variable changes that limit. A github-oauth token for github.com in Composer's auth.json applies to these requests and raises GitHub's rate limit. A failed optional lookup marks only its own advisory as unavailable and does not discard the finding itself or change its audit exit status.

Bun can skip packages from a registry that does not answer its audit request while still returning a successful native status. Foxy therefore treats any diagnostic emitted by bun audit --json as an unreliable partial report and returns status 2 instead of allowing CI to pass on incomplete data.

Audit exit status and CI

The exit status is stable across all supported managers:

Status Meaning
0 The audit succeeded and no advisory met --audit-level.
1 The audit succeeded and at least one advisory met --audit-level.
2 A configuration, manager, lockfile, execution, or report validation failure prevented a reliable audit.

Gate a production build on high and critical findings while retaining a compact log:

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

The explicit command still runs when run-asset-manager is false; that setting controls automatic install and update execution, not a user-requested audit. Foxy must be enabled, the selected binary must satisfy its supported version constraint, and the manager's own lockfile must exist. The native manager has no binary, so only Foxy and foxy.lock are required for it.

Library setup

A Composer library becomes eligible for Foxy when it contains the selected manager's package definition and uses one of the activation methods below.

Required Foxy dependency

Use a runtime dependency when every consumer of the library must process its frontend package:

{
  "require": {
    "php-forge/foxy": "^0.4"
  }
}

Optional development dependency

Use a development dependency when Foxy is optional for library development:

{
  "require-dev": {
    "php-forge/foxy": "^0.4"
  }
}

The consuming application must still require and authorize Foxy because dependencies of a library are not installed from its require-dev section.

Activation through Composer extra

A library can declare itself eligible without adding a Foxy dependency:

{
  "extra": {
    "foxy": true
  }
}

The consuming application must require and authorize Foxy in this case as well.

Package definitions in a subdirectory

When a library stores its frontend package outside its root, declare the relative directory in that library's composer.json:

{
  "config": {
    "foxy": {
      "root-package-json-dir": "resources"
    }
  }
}

Foxy then reads resources/package.json from the installed library. In the root application, the same option controls where Foxy reads and writes the project package.json and where it runs the frontend manager.

The embedded manifest must resolve inside the installed library's Composer directory. Foxy rejects a root-package-json-dir value that resolves outside that boundary.

Embedded package metadata

Foxy creates a local package representation for each eligible Composer dependency. It copies only metadata required for dependency resolution and compatibility checks. Package lifecycle scripts, devDependencies, executable definitions, entry points, and unrelated publishing metadata are not propagated to the consuming application.

Library authors should declare runtime frontend requirements in dependencies, optionalDependencies, or peerDependencies. Any build step needed to publish those assets should run before the Composer package is released, or be configured explicitly by the consuming application.

Manually enabling or disabling packages

The root application can use config.foxy.enable-packages to include a package that does not declare Foxy or to exclude a package that does. See Package selection.

Behavior and guarantees

  • Foxy-managed dependencies use the @composer-asset/ scope and local file: references.
  • Existing project dependencies and development dependencies are retained.
  • package.json writes use four-space indentation and preserve empty object and array semantics.
  • root-package-json-dir controls project reads, writes, and manager working directory.
  • Manager execution does not change the PHP process working directory.
  • The native manager installs one version per package into a flat directory (node_modules unless native-install-dir says otherwise), verifies every tarball against its registry integrity value, and reinstalls from foxy.lock without registry metadata requests.
  • Asset restoration occurs when package merging fails or manager execution throws or returns a non-zero result, and fallback-asset is enabled. It runs before Composer restoration.
  • Composer lock and vendor restoration occurs after any solve exception or non-zero manager result when fallback-composer is enabled.
  • Read, write, and remove failures are reported through exceptions instead of being silently ignored.

Composer restoration does not include the root composer.json bytes. Review that file after a failed composer require or composer remove operation.

Next steps