Skip to content
Development
Skill

/phx-deps-vet

Record a vetted Hex package version in hex_vet.exs after a security review

From plugin
claude-elixir-phoenix
574106 skills37 agents2 commands

Claude Code

$ npx -y skills add oliver-kriska/claude-elixir-phoenix --skill phx-deps-vet --agent claude-code

SKILL.md

phx-deps-vet.SKILL.md
name: phx-deps-vet
description: 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.

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

1. **NEVER auto-approve.** Every entry MUST come from an `AskUserQuestion` confirmation. Drive-by trust ruins the ledger's value. 2. **Lock wins on disagreement.** If `mix.lock` has version X and the ledger vets X-1, emit INFO and treat X as unvetted. Don't silently trust the older entry. 3. **Ledger lives at project root.** `hex_vet.exs` is a first-class security artifact, visible in PR review. Don't move it into `.claude/`. 4. **Round-trip via `inspect/2`.** When appending, read the file with `Code.eval_file/1`, mutate the map, and write back via `inspect(term, pretty: true, limit: :infinity)`. Hand-rolled string appends drift over time. 5. **Always show findings before prompting.** The user must see what's being vetted. No silent `:safe_to_deploy` defaults. 6. **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 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 with `git:`, `github:` or `path:` →

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 the `mix.exs` tuple and what the pin points at, and say that a `branch:`, a missing ref, or a `path:` is mutable: the vet records a decision, not reviewed content. Then Steps 6-7 with `version: "<pin>"`. See hex-vet.md §"Non-Hex dep pins".

  • **`--seed`** → import `priv/hex_vet_seed.exs`. Before prompting,

`Code.eval_file/1` the seed and **compute** (Iron Law #6): the `criteria` split (`Enum.frequencies_by(seed.audits, & &1.criteria)`) and, against any existing ledger, exact new / overwrite / no-op counts. Put those computed numbers in the `AskUserQuestion`. Also state up front that the seed is a **provenance baseline, not certification of your current `mix.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 with `mix.lock`; warn on

drift. Read the lock via `Code.eval_file("mix.lock")` with **`2>/dev/null`** — modern locks have quoted keys and emit a `found quoted keyword` warning per package (tens of KB of noise that gets persisted as an oversized tool result otherwise). Non-Hex pin entries are checked against `mix.exs` tuples, 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 ../phx-deps-audit/scripts/fetch_tarball.sh \
    <pkg> <version>

Step 4: Run Phase 1 rules

Source the rules from `../phx-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 `../phx-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 summ
Read more
@oliver-kriska
Ships withclaude-elixir-phoenix

Docs: phxagents.dev -- install guides per runtime, the runtime compatibility matrix, all 26 Iron Laws, and a browsable skill and agent catalog. Claude Code is great.

574106 skills37 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
574
Star history of oliver-kriska/claude-elixir-phoenix on GitHub, a chart by star-history.com

Other skills on claude-elixir-phoenix.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills11d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc13d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react2d252k
@facebook@facebookInstall Skill

Questions about phx-deps-vet.

Which coding agents can use phx-deps-vet?
phx-deps-vet installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.