// what's next · v0.7.15 · GitHub Action
§ 00 Roadmap npm → Go → beyond

From a Node.js scanner to install-time interception across ecosystems.

phi started as an npm-only behavioral scanner. It's becoming a supply-chain firewall that doesn't care which registry produced the bytes. This page is the overview; per-version release notes live in CHANGELOG.md.

Status legend

shipped released, on GitHub Releases, runnable today
in progress actively being worked on
next up committed direction, queued behind the in-progress item
horizon direction we're going, not committed to dates
out of scope explicit boundary — phi will not become this

Shipped

GitHub Action 2026-08-11

phi audit now runs as a first-class CI step — philtechs-org/phi-action downloads the matching phi binary, scans your npm dependency tree on every pull request, and fails the check when a package comes back BLOCKED. Same detection engine phi watch runs continuously against the public registry, gated at the point a team is actually reviewing a change.

v0.7.13 — Go modules in phi watch; scan-accuracy fixes 2026-08-06

phi watch now monitors Go module paths (github.com/gin-gonic/gin, golang.org/x/tools) alongside npm packages and GitHub repos, running the same Go-specific detector set phi view already used — init() network and filesystem access, cgo plus process execution, build-tag-gated payloads, //go:generate fetching remote code. The scan stream gains an ecosystem filter.

The larger half of this release is scan accuracy. Every fix came from scanning a real, widely-used package and working out why the verdict looked wrong: next@16.3.0 went 65/BLOCKED → 25/REVIEW and three@0.185.1 went 80/BLOCKED → 45/REVIEW. Between them: .npmrc existence probes read as credential theft, vendored polyfills (vm-browserify, setimmediate) read as arbitrary code execution, the V8 toFastProperties hack's deliberately-unreachable eval, hex escapes in a regex character class read as obfuscation, and a package-age signal that measured the current release's publish date rather than the package's first — so every release of every actively-maintained package took a "brand new" penalty for a week afterward. AST-based detection also now runs on ES modules and bundled output, which two unrelated parser issues had been silently downgrading to weaker regex matching. Both headline packages are now in the regression corpus, which runs nightly.

v0.7.12 — phi prune, phi explain, phi doctor 2026-08-05

phi prune removes packages phi.lock/ node_modules still hold but package.json no longer needs, plus anything under node_modules phi never tracked at all (a manual npm install alongside phi, or leftovers from before phi managed the project). phi explain <pkg> extends phi why with the requested version range at every hop in a dependency chain and which package.json section pulled it in. phi doctor bundles environment sanity checks — phi's version against the latest release, registry reachability, lockfile/node_modules consistency, cache size — into individual pass/warn/fail lines. phi cache clean --force now works as the npm-parity alias for --all.

v0.7.11 — phi <script> runs any package.json script by name 2026-08-05

An unrecognized command now falls back to running the matching package.json script when one exists — phi typecheck is the same as phi do typecheck, matching npm <script>'s shorthand. Falls through to the normal "unknown command" error when no script by that name exists, so it never shadows a real phi command or silently swallows a typo.

v0.7.10 — confidence tiers, diff-aware rescanning, real subscriber counts 2026-08-01

Every detection now carries a confidence tier — ast-confirmed, regex-fallback, or regex-only — surfacing a distinction the Arbitrary Code Execution/Dynamic Code Compilation detectors already computed internally but previously threw away: a real AST-parsed eval(...) reads differently from a regex match on a file goja couldn't parse. Shown in phi view, --json output, and on phi watch's package page.

phi watch now computes a sha256 file manifest for every scanned tarball and diffs it against the package's prior scan, rendered as a new "what changed" panel — added, removed, and changed files between two versions, a sharper signal than a bare score delta. When two consecutive scans are byte-identical (a version bump that only touches package.json's version field), the scan skips the analyze/advisory/reputation pipeline and copies the exact prior verdict forward instead of recomputing an equivalent one.

Package pages also show a real subscriber count (developers watching that package) instead of the earlier placeholder.

v0.7.9 — reputation-weighted scoring, score sparkline, webhook alerts 2026-08-01

Scores now get a small, transparent adjustment (-10 to +15) based on a package's publish age and maintainer count — signals already in every npm packument. A brand-new, single-maintainer package nudges a borderline score up; a long-established one nudges it down. It's a third scoring stage after detectors and advisories, never overrides a confirmed-malicious verdict, and always explains itself via a notices entry when it applies. Applies across phi view, phi install/phi audit, and phi watch.

phi watch's package page gained a historical score sparkline, and users can now set a generic outbound webhook (Slack/Discord/PagerDuty/anything) alongside or instead of email alerts — shipped with SSRF protection (HTTPS-only, private/loopback/link-local/cloud-metadata IPs rejected, no redirect-following) since it's the first place phi watch makes a request to a user-supplied URL.

v0.7.8 — confirmed-malicious advisories force an unconditional block 2026-08-01

An OSV MAL-* advisory (GitHub/OSV's confirmed- malicious classification) now forces Score=100/blocked outright instead of contributing points like an ordinary CVE — "this is malware" is a certainty, not a probability to weigh against detector noise. phi view/phi audit --json gained a dedicated malicious field, distinct from a generic BLOCKED verdict, with a ☠ CONFIRMED MALICIOUS banner in text output. Credential Theft was also downgraded from CRITICAL to HIGH — a bare credential-file read alone shouldn't carry the same weight as a confirmed outbound exfil call.

v0.7.7 — advisory-only threats no longer score 0/SAFE 2026-08-01

A tarball npm scrubbed down to an empty placeholder (a security-holding-package takedown) has nothing left for detectors to find, so the whole verdict rode entirely on the OSV advisory — but MAL-* IDs never carry a CVSS severity, so they fell through to a generic 5-point "LOW" weighting that wasn't enough to leave a package flagged as safe. MAL-* advisories are now weighted as CRITICAL regardless of reported severity, everywhere advisory points are merged.

v0.7.1 – v0.7.6 — false-positive hardening pass; phi watch tracks GitHub-sourced packages 2026-07-31 – 2026-08-01

A run of detector-accuracy fixes against real packages — skills, fastify, next, zod, cowsay, nx, create-react-app — tightening Credential Exfil Flow/Credential Theft's canonical-host checks, teaching Arbitrary Code Execution/Dynamic Code Compilation several well-known bundled-dependency idioms (ajv's minified validator codegen, @vercel/nft, depd's deprecation wrapper), stripping comments/prose before regex fallback so remarks and doc strings stop matching as if they were real calls, and excluding source-attribution comments from Network Exfiltration. Every detection also gained a line number, and evidence snippets now show the real matched source (not a fixed template) at up to 240 characters instead of 80.

phi watch gained support for GitHub-sourced packages (the same owner/repo shorthand phi view already accepts), authenticated GitHub API requests (raises the rate cap from 60/hr to 5000/hr once polling multiple repos), and captures each package's npm description for the dashboard.

v0.7.0 — phi audit connects to phi watch; dist-tag view fix 2026-07-31

phi audit now cross-checks each direct dependency against phi watch's public feed — if watch has seen a worse verdict since your last local scan, it's called out by name. --submit-watch opts a run into publishing its scanned packages to that feed; off by default, nothing leaves your machine unless you pass it. A new local-only drift check also compares each package's verdict at last install (phi.lock) against its current audit verdict, so a package that's silently gone from SAFE to flagged gets surfaced by name — directly answering "why didn't phi update catch this" (a caret range can't reach a major bump; drift tells you which package needs an explicit one).

Fixed: phi view <pkg>@<tag> now resolves npm dist-tags like latest or next, not just exact versions.

v0.6.9 — phi audit recommends verified upgrade targets 2026-07-08

phi audit now recommends what to upgrade a flagged package to, not just its score — advisory fixes use OSV's known-good version, and scanner-flagged packages with no advisory get a candidate rescanned and only recommended if the score actually improves. Recommendations distinguish an in-range bump (phi update reaches it) from a breaking one, and phi audit fix can now apply scanner-verified bumps too.

v0.6.8 — fix: phi rebuild runs scripts with node_modules/.bin 2026-07-08

phi rebuild now runs lifecycle scripts with node_modules/.bin on PATH, so a postinstall that calls node-gyp, the prisma CLI, or any dependency binary works. One failing script no longer aborts the batch, successes read as status instead of warnings, and packages run in the order named.

v0.6.7 — fix: install actually extracts GitHub-sourced deps 2026-07-07

phi install/phi ci now extract a git-sourced dependency into node_modules instead of resolving it and stopping short.

v0.6.6 — GitHub-sourced package scanning 2026-07-07

phi now resolves and scans packages that live only on GitHub instead of a registry — npm dependencies written as github:owner/repo#ref, and phi view owner/repo for one-off lookups. Fetched via the GitHub API and codeload.github.com, scored through the same analyzer pipeline as any registry package. .phi-allow supports the resulting owner/repo@ref identity.

v0.6.5 — script opt-in, multi-package view, Go trust allowlist 2026-07-06

phi rebuild <pkg…> lands as the explicit, per-package opt-in to lifecycle scripts. A plain phi install still runs none by default — and now ends with an advisory listing any package whose preinstall/install/postinstall hooks it skipped, printing the exact phi rebuild line to enable them.

phi view now inspects several packages at oncephi view nodemailer express resend renders a card each plus a per-package verdict summary, and --json emits an array. Every flag across phi view and the install/audit report cards now shows the reason behind it — severity, the matched evidence:, and the file: — so a BLOCKED verdict explains itself instead of sending you back to re-run a scan.

v0.6.4 — optional dependencies + install UX 2026-05-30

optionalDependencies are now resolved by default with platform-aware filtering. Modern dev tooling that ships native binaries this way — vite, rollup, esbuild, swc, lightningcss, sharp — finally installs cleanly. The resolver reads each package's os and cpu fields and silently drops platform mismatches the same way npm does; a packument failure on an optional entry is also silent. --omit=optional becomes meaningful and reinstates the previous strict behavior.

The install flow now runs in two phases: safe packages extract immediately after the scan, then the review prompt fires with the full per-detection breakdown inline — severity badge, detector, the why: description, the matched evidence:, and the file: path. No more scrolling up to remember what you're approving. Review-approved packages and any safes that were deferred because their closure touched a pending review then extract in a second pass.

v0.6.3 — detector accuracy, strict-closure, phi watch goes live 2026-05-29

The detector pipeline was tuned to clear false positives on popular bundled CLIs and packages with embedded binary data. prisma (score 100 → 35) and pdfjs-dist (90 → 20) no longer land in the BLOCKED tier: their hex-escape charset tables, embedded OpenType / TrueType fonts, bundler eval("__dirname") recovery shims, and .npmrc reads by legitimate native-binary installers all stopped tripping detectors without weakening coverage of real attacks. Six new regression tests pin the contract.

phi install gains --strict-closure / PHI_STRICT_CLOSURE: a CI gate that bails before writing phi.lock when any package would be pruned due to incomplete dep closure. Without the flag, partial-prune installs now exit non-zero so CI pipelines notice the incompleteness without re-reading the per-package warnings.

v0.6.2 — closure-consistency pruning during install 2026-05-23

phi install now iteratively prunes packages whose transitive dependency closure is incomplete — typically when a parent in the resolved tree has a dep that itself failed scan, was excluded by --omit, or has no available tarball. The previous behavior would install the parent with dangling refs, leaving node_modules in a state where requires could fail at runtime.

A fixed-point algorithm walks until no further pruning is needed, records each skip reason (blocked transitive, missing tarball, removed from tree), and surfaces the list of affected direct deps in the install report so the user knows exactly what to address.

v0.6.1 — npm installer resilience and verification 2026-05-23

npm installs are now best-effort: phi installs resolved SAFE packages first, reports unresolved packages after extraction, skips BLOCKED packages unless --force is used, and queues REVIEW packages for an explicit approval step.

Accepted REVIEW packages are remembered in phi.lock, so repeated installs do not ask again for the same accepted package version. CLI flags such as --yes and --no-advisories are parsed as installer flags instead of package names.

New phi check / phi verify validates package.json, phi.lock, installed package directories, cached tarball integrity, and installed files when a cached tarball is available. Registry fetches also gained retries, a longer default timeout plus PHI_REGISTRY_TIMEOUT, PHI_REGISTRY_ATTEMPTS, and PHI_REGISTRY_RETRY_DELAY for slow networks.

v0.6.0 — multi-ecosystem: Go modules support 2026-05-16

phi becomes a polyglot supply chain firewall. Auto-detects Go modules (go.mod, go.work) and routes to the new hybrid replace pipeline: shells out to go mod download into a phi-controlled staging dir, scans every fetched zip with the analyzer + OSV, then atomically materializes approved bytes into $GOMODCACHE. BLOCKED modules never reach Go's cache without an explicit override.

Full command surface: phi install, install <mod>@<v>, update, remove, audit, audit fix, outdated, upgrade-interactive, view, why, ls, build / test / run / vet / fmt, doc, replace / unreplace, init --go. Plus Go-toolchain aliases (phi mod tidy = phi install, phi get = phi install, phi mod verify = phi audit, etc.) and the universal phi go <anything> escape hatch.

Go workspaces (go.work) — multi-module monorepos walk every use directive with a per-member phi.lock and an aggregate verdict summary. Binary install (phi install <tool>@latest outside a project) gates global Go tools through the same scan pipeline before go install writes to $GOBIN. Vendor via phi mod vendor. Cross-compile sugar (phi build --cross linux/arm64). Replace /unreplace wrappers with cross-org-fork detection.

Six new Go-specific detectors: go-init-network, go-init-fs-write, go-cgo-shellexec, go-build-tag-gated, go-go-generate-curl, go-unsafe-import. Plus the project-level go-replace-with-fork. Schema-v3 phi.lock with a tagged source.type union covers npm and Go in one file. Verdict cache (h1-keyed, content-addressed) cuts warm-cache install time ~50%. .phi-allow persistent project allowlist. Retraction + deprecation warnings surfaced on install. sum.golang.org transparency status in audit footer.

v0.5.1 — phi view scans by default; live spinners 2026-05-16

phi view <pkg> now runs the detector pipeline + OSV check on the resolved tarball and prints a security: block (score, verdict, detections, advisories with fix versions) alongside the standard metadata. Same engine phi install and phi audit use — so you get the same verdict you would get if you installed the package, before you add it. --no-scan opts out for scripting; field-targeted queries (phi view react license) auto-skip. Spinners now cover phi view, phi outdated, and phi upgrade-interactive so long-running phases never look stuck. phi help rewritten and grouped by lifecycle.

v0.5.0 — workspace tooling and developer ergonomics 2026-05-15

The biggest single drop of CLI ergonomics so far. Tier 1 features: phi ls (npm-style ASCII trees), workspace: protocol (workspace:*, workspace:^1.0.0, path-relative form), phi link / phi unlink (Windows junctions, no admin), and phi do --filter (pnpm-style selectors). Tier 2: phi view packument inspector, phi config with secret redaction, phi pkg dot-path editing, and phi upgrade-interactive. Plus --omit=dev,optional,peer, env var equivalents (PHI_OMIT, PHI_CI, …), and phi cache clean --runs / --all-caches for stage cache eviction.

v0.4.2 — typed registry errors & resilient audits 2026-05-15

Registry failures now surface with the right shape: a non-existent package gets a clear not found · check the spelling or whether it's private instead of a raw 404 Not Found string. phi audit no longer dies on the first registry failure — transient or missing packages are recorded in phi-report.json's new skipped array and the rest of the tree is scanned. Registry fetches retry up to 3× with exponential backoff (500ms / 1s / 2s) + ±25% jitter on network errors, 429 rate-limits, and 5xx; Retry-After honored. The spinner now shows resolving... (retrying X · N total) so flaky networks are visible instead of looking like a hang.

v0.4.1 — phi ci for production installs 2026-05-11

phi ci is the canonical one-line install for non-interactive environments (Docker builds, GitHub Actions) — sugar for phi install --frozen-lockfile --yes. The frozen lockfile is the audit record: anything in phi.lock was already reviewed and approved by the developer during their local install, so prod can auto-approve review verdicts without a prompt. Blocked verdicts still abort unless --force. Plus two composable primitives: -y/--yes (auto-approve reviews on any install/update) and --omit=dev (skip devDependencies, npm parity).

v0.3.0 — phi x, scan-and-run like npx 2026-05-10

phi x <pkg> now mirrors npx: if the bin isn't already in node_modules/.bin, phi resolves the providing package, runs the full scanner + advisory pipeline over the transitive tree, then runs the bin from a per-version cache without polluting your node_modules. A scan-passed marker means repeat invocations skip straight to running. Pinned versions, scoped packages, bin-name-≠-package-name (phi x -p typescript tsc), and the -- separator all work the npx way. Lifecycle scripts stay off — phi-stricter than npx by design. Plus an animated resolver spinner with the first frame drawn immediately — no more silence between banner and progress.

v0.2.5 — robustness + better Windows experience 2026-05-09

Mid-install interruption can no longer corrupt your package.json. Bad packages can no longer crash a scan run. Friendlier first-run experience on Windows.

v0.2.3 — auto-fix + uniform progress UI 2026-05-08

phi audit fix [--apply | --force] — proposes safe fixes for typosquats, vulnerable versions, and deprecated packages. Preview by default; you opt in to applying. Scan progress now renders consistently across every shell we ship to.

v0.2.2 — supply-chain detectors 2026-05-08

Two new behavioral detectors targeting recent threat patterns (credential exfiltration flow + Linux system tampering), plus deprecation guidance for packages with safer successors.

v0.2.1 — self-update 2026-05-08

phi self-update brings phi current with one command. Verifies the new binary against published checksums before swapping.

v0.2.0 — scaffolding + force 2026-05-08

phi create bootstraps React, Next, Express, Fastify, or Nest projects — with the scaffolder itself audited first. --force escape hatch for packages you know you trust despite a flagged verdict.

v0.1.0 – 0.1.2 — foundation 2026-05-07

The install-time interception pipeline: 19 detectors (npm + Go), OSV vulnerability layer, lifecycle scripts off by default, lockfile + audit report, cross-platform binaries.

In progress

Code signing for Windows release artifacts

Cleans up the install experience on first run. Same binary, signed.

Next up

Nothing queued right now — tell us what npm workflow still feels rough.

On the horizon

Directional, not committed to dates. Order is rough priority.

Python (PyPI) ecosystem support

Rust (crates.io) ecosystem support

IDE integration

Live scan as you edit your manifest.

CI integrations

First-class GitHub Action, GitLab CI templates, drop-in for the major platforms.

Sandboxed dynamic analysis

Opt-in per package; results feed the same risk score.

Custom detector plugins

Strict trust model — signed plugins only.

Out of scope

phi will not become these things. Listing them here so the boundary is explicit.

Runtime sandbox

phi is install-time only. Once code is in node_modules/ and your app runs it, that's the application's concern — use container limits, gVisor, or an EDR for that.

Forced migration

phi.lock is a complete, integrity-verified lockfile — phi can be your only package manager, in CI, in Docker, in production. But if you'd rather keep package-lock.json / yarn.lock / pnpm-lock.yaml alongside for tooling that expects them, phi leaves them alone. Drop-in, not rip-out.

Telemetry / centralized policy

No daemon. No phone-home. Ever. Decisions happen on your machine, with your data, full stop.

Paid SaaS tier on the install path

phi stays free and open-source. Commercial offerings would be separate products built on top — never behind a paywall on the install path itself.

Influence the roadmap