nunomaduro/pet
Pet is a lightweight PHP ETL package for Laravel and plain PHP apps. It offers a simple, expressive API for extracting, transforming, and loading data between sources, making it easy to build clean, testable data pipelines.
Architecture fit. Vet remains a dev-time static analysis CLI for Composer dependency graphs — it audits what is already in composer.lock rather than instrumenting the application. No service provider, container bindings, middleware, or production config surface. It sits in the same tier as PHPStan, Pint, and Rector and should be governed by the same quality-gate policy. One refinement prompted by v0.2.1: the tool now demonstrably reads a committed, repo-local declarative config (vet.json), which means it introduces a versioned artefact into each repository — small, but it is a file engineers will edit, review, and eventually copy between repos. That shifts Vet marginally from "pure CLI flag-passing" toward "policy-as-config," which is a better fit for fleet-wide governance but adds a schema to own.
Integration feasibility. High. Install is a single composer require --dev line or global install; invocation is a CLI command suitable for a CI step, pre-push hook, or scheduled job. v0.2.1 confirms the two integration properties that matter: (a) configuration is file-based and therefore reviewable and diffable in PRs, and (b) the config supports at least one policy primitive beyond advisories. The remaining unknowns are unchanged — non-zero exit on findings, severity threshold flags, and machine-readable output — but the existence of vet.json makes a machine-readable config surface likely and gives a natural place for a central baseline.
Technical risk. Low absolute risk, moderate decision risk. v0.2.1 is a patch with no breaking changes; it does not alter the risk profile materially, but it reveals capability and maturity signals that do:
| Risk | Severity | Note |
|---|---|---|
Overlap with composer audit |
Low–Medium (was Medium) | The "minimum release age" setting is a genuine differentiator: composer audit checks advisories, it does not enforce a cooldown window against freshly published versions. That is a supply-chain compromise defence native Composer does not offer. The delta question is now largely answered — validate the implementation, not the premise. |
| Config schema immaturity | Medium (new) | A v0.2.1 patch whose subject is "allow an empty vet.json with only minimum release age settings" indicates the config schema is young and its validation has had gaps. Pre-1.0 semver means vet.json field names and semantics can change on a minor bump. Pin the version and treat config changes as reviewable code. |
| Minimum-age policy vs. emergency patching | Medium (new) | A cooldown window is a deliberate brake on adoption of new versions. The same brake blocks an urgent security upgrade. The tool must support per-package overrides or a documented bypass, or the first CVE will force engineers to disable the gate under pressure. |
| Maturity signal | Medium | Still small install base and no downstream validation pool. Unchanged by this release. |
| Advisory/registry data dependency | Medium | Both advisory feeds and release-timestamp metadata are external CI dependencies; the minimum-age feature adds a second data source (version publish times) with its own freshness and availability characteristics, including for private or path-repo packages where no publish time exists. |
| Artifact identity mismatch | High (governance) | Unresolved and still blocking. The supplied package name (nunomaduro/pet) does not match the repository (laravel/vet). Confirm the Composer package name resolves to the official repo with verified tags before install. |
| False-positive CI gating | Medium | Unchanged, and the new policy dimension adds a class of "finding" that is not a vulnerability at all — just a version that is too new. Noise budget must be set deliberately. |
Key questions to resolve before a pilot.
vet.json schema documented and versioned, and is there a compatibility guarantee for it across 0.x minors?composer audit does not, now that minimum-age is on the table — and is that delta worth a second tool in the pipeline?Stack fit. Strong for a Laravel/PHP estate on Composer 2 — no polyglot friction, no separate runtime, no sidecar. The committed vet.json fits existing repo conventions alongside phpstan.neon, pint.json, and .php-cs-fixer.php, and gives a natural anchor for a shared baseline.
Migration path. Nothing to migrate. Purely additive. Frame as trial with an explicit exit criterion so removal is a non-event.
Compatibility. Three axes now, not two: the tool's PHP constraint against the oldest PHP in the CI matrix; behaviour on monorepos and path repositories where composer.lock and publish-timestamp semantics differ; and the vet.json schema against whatever shared baseline you publish. Test the minimum-age feature specifically on the repo with the most path/VCS dependencies — that is where timestamp resolution is most likely to be undefined or wrong.
Sequencing.
vet.json with minimum-age enabled but non-enforcing so you can see what it would have caught.composer audit over 2–3 weeks. Count unique findings, split advisory findings from age findings, count false positives and time-to-triage.Maintenance. Near-zero engineering cost: a pinned dev dependency, one CI line, one small committed config file. The real maintenance is policy maintenance — waiver hygiene, severity thresholds, and now the minimum-age window, all of which drift if unowned. Assign a named owner for the waiver list and the age threshold, or they become a graveyard of suppressed findings. Pin the exact version: a pre-1.0 config schema plus a CI parser downstream is a fragile combination.
Support. Community-only, MIT, effectively single-maintainer. No vendor SLA. Escalation path for a blocking false positive is "patch locally or disable the gate" — acceptable for dev tooling, but document it as the accepted fallback so teams don't improvise under release pressure.
Scaling. Cost scales linearly and cheaply with repo count and CI minutes. The limit is organisational: at ~20+ repos, per-repo vet.json files diverge and the same advisory or age violation is triaged independently by every team. The existence of a config file makes a shared baseline feasible — plan a central config repo (or a published preset) from the start rather than retrofitting one.
Failure modes.
vet.json parses under the pinned version.Ramp-up. Under a day for an engineer to install and interpret. The expensive part is the 2–3 week shadow period needed to build trust in the signal, plus a short calibration of the minimum-age value against real release velocity. Budget for it — teams that gate on day one and get burned will not re-adopt.
Verdict on v0.2.1. A low-risk patch, but a useful signal: it confirms a reviewable config surface and surfaces a capability — release cooldown — that is a credible reason to run Vet alongside native composer audit. No change to the overall recommendation: a cheap, reversible, low-ceiling bet worth a scoped pilot, still contingent on resolving the package-identity question and validating the minimum-age behaviour on the messiest repo first.
How can I help you explore Laravel packages today?