npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zincapp/znvault-plugin-appliance

v0.1.2

Published

Manage the appliance holding the hardware root of trust for the ZnVault bootstrap key

Readme

@zincapp/znvault-plugin-appliance

Manage the appliance that holds the hardware root of trust for the ZnVault bootstrap key (BSK), from the znvault CLI. This is a plugin for @zincapp/znvault-cli (>= 2.11.0); installing it adds the znvault appliance … command family.

Status: v0.1.0 — never run against a real appliance. Every command here is unit-tested against fakes only; nothing in this repository has ever touched real hardware. At the same time, the box this tool is written for holds a production root of trust: the daemon it manages answers the vault's boot-time key requests. Treat every mutating command as unproven — read the plan output, use --dry-run, and keep a console session to the appliance open the first time you run anything with --confirm.

npm install -g @zincapp/znvault-plugin-appliance
znvault appliance status

The invariant that shapes everything here

This plugin must work with the vault DOWN. The appliance is what the vault boots from, so a tool that needs a live vault to fix the appliance is useless exactly when it is needed.

That inverts the usual plugin pattern. Every command declares two planes:

| plane | transport | needs the vault | |---|---|---| | appliance | ssh with your own key → the daemon's own CLI | no | | vault | superadmin rootkey … through the CLI client | yes |

The appliance half always runs. The vault half degrades loudly — never silently, and never into a green result.

Two consequences worth knowing before using it:

  • The local profile file is the source of truth. It stores values (host, ssh user, paths, the golden KCV), not vault pointers, because a pointer needs a live vault to resolve. There is no vault-stored copy; a second copy is drift.
  • The transport is plain ssh, deliberately not the vault's SSH-CA tunnel — that path rides the vault's own CA and dies with the vault.

Commands

| command | does | vault | mutates | |---|---|---|---| | appliance profile add\|list\|use\|rm | local profiles: host, ssh user, source dir, venv, config path, golden KCV | no | no | | appliance status | daemon status + provenance + unit state, merged with the vault's root-key status when reachable | degrades | no | | appliance verify | full gate: appliance + strict all-provider rootkey verify + golden-KCV match | required for a verdict | no | | appliance audit verify\|tail | walk the audit chain; tail the daemon journal | no | no | | appliance window status\|close | report / close the wrap window | no | yes (close) | | appliance upgrade | backup → rsync → reinstall → preflight → restart → assert → KCV gate | gated (see below) | yes |

There is no window open, and there will not be one

The daemon's own CLI states why: "a wrap window that could be opened over the network would defeat the physical-presence gate it exists to be". Opening the window is a human at the console. Closing it is offered here, because closed is the safe state — and the daemon does not roll a close back, so a failed audit row after a close is reported as "the window is CLOSED, but…", never as a failed close.

Exit codes

The daemon's contract is three-valued and this plugin keeps it that way. The distinction is the point: collapsing 1 and 2 turns "your audit chain is broken" into "bad flag".

| code | meaning | |---|---| | 0 | ok | | 1 | the appliance answered and reports a problem (broken audit chain, KCV mismatch, a failed assertion) | | 2 | the command could not run: bad usage, a fail-closed config, a missing profile. Nothing was inspected | | 3 | a plane was unreachable (ssh transport, or the vault leg when a verdict needed it) | | 4 | an answer outside the documented contract |

Getting started

# 1. Describe the appliance. Nothing here is guessed: --host AND --ssh-user are
#    both required and both yours — this tool ships no default account name.
znvault appliance profile add anchor --host appliance.example.com --ssh-user operator --use

# 2. Look at it. Works with the vault down.
znvault appliance status

# 3. Full gate. The FIRST successful verify records the golden KCV in the profile.
znvault appliance verify

The golden KCV is never invented. It stays absent until a verify actually observes one, and once recorded, no command offers a way around a mismatch.

Targeting a non-active profile: --appliance, deliberately not --profile

Every subcommand accepts --appliance <name> to run against a profile other than the active one. The flag is not named --profile on purpose: the host CLI owns a global --profile <name> (its vault profile — the house idiom is znvault --profile prod <cmd>), and a subcommand option of the same name would silently shadow it. znvault appliance verify --profile prod would then aim the appliance leg at the prod appliance while the vault leg hit whatever CLI profile happened to be active — two planes of one command pointed at different targets, with the host's own fail-closed unknown-profile guard never firing. A test asserts no option registered by this plugin is ever named profile.

Upgrading the daemon

upgrade is the hand-run procedure, transcribed, with its gotchas encoded. It is a plan by default:

znvault appliance upgrade --source ./zn-trust-root          # plan + read-only recon
znvault appliance upgrade --source ./zn-trust-root --confirm appliance.example.com

Guard order, and the order is the design:

  1. --confirm <host> must equal the profile's target exactly, checked before any process runs.
  2. The vault KCV pre-gate: every provider matches, the independent second root is healthy, and the active KCV is the profile's golden value. If the vault is unreachable the upgrade blocks — override with --no-vault-gate, which additionally requires --confirm and states in its own output that the KCV gate did not run.
  3. The remote identity assertion: the box must present a hostname, the source tree, the venv interpreter, the live config and the daemon unit. It fails closed.
  4. Only then: backup → rsync → chown → reinstall → preflight → restart → post-checks → the KCV post-gate.

What the plugin knows about the box, so you don't have to remember

  • rsync -a shipped the files as the local uid where the originals were root-owned. This already broke a real deploy, so --no-owner --no-group is mandatory here and a chown -R root:root follows it.
  • The source tree is a plain rsync'd directory, not a git checkout — "update the checkout" is an rsync, never a git pull.
  • There is no sqlite3 on the box. The policy-store assertion runs through the venv's own python, and reads column names, trigger names and a row count — never a stored value.
  • provenance and --version may be absent on the deployed build. Absence is reported as a fact about that build, never as a failure.
  • The live config is not touched by an upgrade, and that is asserted by comparing its digest before and after.
  • Store migrations are one-way: the backup restores code, not state. The plan says so before anything runs.

What this plugin will never do

  • Invoke wrap or unwrap, or open a wrap window.
  • Touch any bootstrap-key file, or the independent second root.
  • Offer a force path around a KCV mismatch.
  • Carry a host name, address, account name, serial or KCV value in its source. Those live in your local profile file; this repository uses example.com, neutral placeholder accounts and RFC 5737 documentation addresses, and a shape-based test (test/no-topology.test.ts) enforces it without itself naming anything real.
  • Default an ssh account name. --ssh-user is required on profile add precisely so no real account name ever needs to exist in this repository.

Requirements

  • Node.js >= 20
  • @zincapp/znvault-cli >= 2.11.0 (the host CLI that loads this plugin)
  • ssh and rsync on your workstation, with your own key installed on the appliance — this plugin never manages credentials

Development

npm install
npm run build
npm run typecheck
npm run lint
npm test

Everything is unit-tested against a fake plugin context and a scripted process runner — no test touches an appliance, a network or an ssh binary. Which is the other half of the status warning at the top: the test suite proves the plugin's contracts, not the appliance's behaviour.

License

MIT © ZincApp SL