/phx:deps-vet
Record a vetted Hex package version in hex_vet.exs after a security review — manages the audit ledger, not the scanner. Use to approve a dep after /phx:deps-audit findings or to initialize hex_vet.exs.
Synopsis
/phx:deps-vet <pkg> <version> | <dep> <pin> | --seed | --list | --check
Invoke in v3
Compare runtime support →/phx:deps-vet Amp skill: invoke → phx-deps-vet Codex $elixir-phoenix:phx-deps-vet Pi /skill:phx-deps-vet OpenCode skill tool → name: "phx-deps-vet" DeepSeek Harness /phx-deps-vet Claude Code includes the full custom-agent and hook layer. Generated runtimes load the same skill knowledge with runtime-native invocation.
On this page
Deps Vet — Hex package audit ledger
Review a Hex package version, run Phase 1 supply-chain rules against it,
prompt the user for a verdict, append the result to hex_vet.exs
(project-root audit ledger). Vetted versions get downgraded to INFO
on subsequent /phx:deps-audit runs.
Run this AFTER /phx:deps-audit to clear findings.
Run this BEFORE merging a mix.lock PR to certify new versions.
Usage
/phx:deps-vet phoenix 1.7.21 # vet a single package version
/phx:deps-vet my_dep github:org/repo@tag:v1.0 # vet a git/github/path dep pin
/phx:deps-vet --seed # import curated baseline seed (~30 pkgs)
/phx:deps-vet --list # show existing ledger entries
/phx:deps-vet --check # cross-check mix.lock vs ledger
Iron Laws
- NEVER auto-approve. Every entry MUST come from an
AskUserQuestionconfirmation. Drive-by trust ruins the ledger’s value. - Lock wins on disagreement. If
mix.lockhas version X and the ledger vets X-1, emit INFO and treat X as unvetted. Don’t silently trust the older entry. - Ledger lives at project root.
hex_vet.exsis a first-class security artifact, visible in PR review. Don’t move it into.claude/. - Round-trip via
inspect/2. When appending, read the file withCode.eval_file/1, mutate the map, and write back viainspect(term, pretty: true, limit: :infinity). Hand-rolled string appends drift over time. - Always show findings before prompting. The user must see what’s
being vetted. No silent
:safe_to_deploydefaults. - Confirmation counts are COMPUTED, never estimated. Any number in
an
AskUserQuestion(criteria split, new/overwrite/no-op) MUST be derived from the loaded data before prompting — e.g.Enum.frequencies_by(seed.audits, & &1.criteria). Eyeballing the file and approving on wrong numbers corrupts the consent.
Execution flow
Step 1: Locate or seed hex_vet.exs
If hex_vet.exs exists at project root:
Read it via Code.eval_file/1
Else:
Write the empty-ledger stub (see ${CLAUDE_SKILL_DIR}/references/hex-vet.md §"Empty ledger")
Inform user: "Created hex_vet.exs at project root. Its policy is
block_on_unvetted: :new_only, so the deps gate now BLOCKS `mix deps.get`
when a new unvetted dep appears (it was warn-only without a ledger).
Set it to false to keep warn-only."
The stub always writes policy.block_on_unvetted explicitly. Never create a
ledger without it: the gate infers :new_only from a bare ledger, and that
silent switch from warn-only to blocking surprises users.
Step 2: Branch by mode
<pkg> <version>→ single-vet path (Step 3-7).<dep> <pin>where the pin starts withgit:,github:orpath:→ non-Hex path. Use the exact pin the gate printed (/phx:deps-vet my_dep github:org/repo@tag:v1.0); the gate matches it character for character. Skip Steps 3-4 (no Hex tarball). Show themix.exstuple and what the pin points at, and say that abranch:, a missing ref, or apath:is mutable: the vet records a decision, not reviewed content. Then Steps 6-7 withversion: "<pin>". See hex-vet.md §“Non-Hex dep pins”.--seed→ importpriv/hex_vet_seed.exs. Before prompting,Code.eval_file/1the seed and compute (Iron Law #6): thecriteriasplit (Enum.frequencies_by(seed.audits, & &1.criteria)) and, against any existing ledger, exact new / overwrite / no-op counts. Put those computed numbers in theAskUserQuestion. Also state up front that the seed is a provenance baseline, not certification of your currentmix.lock(per Iron Law #2, seed versions older than the locked ones stay unvetted). Ask before overwriting existing entries.--list→ render the audits table; exit.--check→ compare ledger entries withmix.lock; warn on drift. Read the lock viaCode.eval_file("mix.lock")with2>/dev/null— modern locks have quoted keys and emit afound quoted keywordwarning per package (tens of KB of noise that gets persisted as an oversized tool result otherwise). Non-Hex pin entries are checked againstmix.exstuples, not lock versions.
Step 3: Fetch the tarball (single-vet)
Run the deps-audit corpus loader. Cache lives at
~/.cache/phx-deps-audit/corpus/<pkg>/<version>/contents/. Use:
bash ${CLAUDE_SKILL_DIR}/../deps-audit/scripts/fetch_tarball.sh \
<pkg> <version>
Step 4: Run Phase 1 rules
Source the rules from ../deps-audit/references/rules-impl.md.
Run run_all_rules over the cached dir. Write findings to a temp
vet-findings.jsonl. Set FINDINGS_FILE to override default path.
Step 5: Present findings
Print the findings table per ../deps-audit/references/output-renderer.md.
On zero findings: say “No findings — vet from a clean baseline.”
On any finding: show severity, file, line, snippet inline.
Step 6: Prompt for verdict
Call AskUserQuestion with these 4 options:
:safe_to_deploy— full trust; findings investigated and cleared.:safe_to_run— trust in non-production envs only (test deps).:does_not_implement_crypto— Mozilla-style sub-criterion.Skip— defer decision; don’t write an entry.
If any finding is BLOCK severity: default-highlight Skip. Require
explicit override before writing :safe_to_deploy over a BLOCK.
Step 7: Append to ledger
Read existing hex_vet.exs via Code.eval_file/1. Append the audit
map below to :audits. Write back via
Code.format_string!(inspect(...)).
%{
package: "<pkg>",
version: "<version>",
criteria: <verdict_atom>,
reviewer: "<git config user.email>",
notes: "<user-provided one-liner OR findings summary>",
reviewed_at: ~D[<today>]
}
Write back via Code.format_string!(inspect(term, pretty: true)).
Confirm to user: “Added <pkg> <version> to hex_vet.exs.”
Integration
- Run after
/phx:deps-auditto clear vetted findings. - Run before merging a
mix.lockPR to certify new versions. - Run
/phx:deps-vet --checkto detect ledger drift vsmix.lock. /phx:deps-auditauto-downgrades vetted findings to INFO.policy.block_on_unvettedis enforced by the plugin’sdeps-audit-gate.shPreToolUse hook onmix deps.get/mix deps.update.
References
${CLAUDE_SKILL_DIR}/references/hex-vet.md— schema, parser, lookup${CLAUDE_SKILL_DIR}/references/seed.md—--seedflag, curated baseline${CLAUDE_SKILL_DIR}/../deps-audit/references/rules-impl.md— the same rules/phx:deps-auditruns
Out of scope (Phase 3+)
- Mix task surface — defer
mix phx.deps_vetto a separate Hex packagephx_deps_vetfor non-CC users. - Distributed imports — defer cargo-vet
imports:until trust-chain semantics are designed.