Package Exports
- @ajna-inc/npmvc
- @ajna-inc/npmvc/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@ajna-inc/npmvc) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@ajna-inc/npmvc
Supply-chain credential system for npm. Sign attestations when you publish, verify every dependency when you install.
Pure TypeScript. Zero native dependencies. Works everywhere npm runs.
Quick start — consumer
npm install -g @ajna-inc/npmvc
npmvc install-hook # default preset: "balanced"
# or:
npmvc install-hook --preset strict # block on unattested too
npmvc install-hook --preset permissive # warn-only, never blocksThis adds a preinstall hook to your package.json and writes
npmvc-policy.json. Every subsequent npm install then runs
npmvc verify first.
What each preset does
| Preset | Bad signature | Tampered bytes | Revoked credential | Unattested dep |
|---|---|---|---|---|
strict |
block | block | block | block |
balanced (default) |
block | block | block | warn |
permissive |
warn | warn | warn | warn |
Most of npm is still unattested, so balanced warns on unattested
deps but blocks the explicitly-bad ones. Flip to strict once your
internal packages are all attested.
There is no env-var bypass. To temporarily disable, edit
package.json#scripts.preinstall directly.
Quick start — publisher
npm install -g @ajna-inc/npmvc
npmvc init # plaintext key
# or:
npmvc init --encrypt --passphrase "..." # encrypted at rest
npm pkg set "publisher"="$(jq -r .did ~/.npmvc/wallet/key.json)"
npm pkg set scripts.prepack="npmvc attest --registry https://npmvc.com"
npm pkg set files='["dist", ".npmvc"]' --jsonEvery subsequent npm publish now runs attest first: signs
Provenance + Lifecycle + SBOM credentials, binds them to the content
of the tarball, and uploads to the npmvc registry.
To rotate the keys you sign with, see SECURITY.md.
What gets checked
- Signatures — DSSE envelopes verified against publisher DID (Ed25519)
- Tarball digest — installed bytes are hashed and compared to the signed claim
- Revocation — credentials revoked by the publisher are refused
- Age — versions younger than
minAge(default 7d) are flagged - Publisher continuity — DID changes across versions block (
did:webvhrotations are allowed via SCID-prefix matching) - Trust root —
trustedIssuersURL fetched, Ed25519-signed by the pinned root DID - Lifecycle scripts —
postinstallflagged unless whitelisted - Transitive deps — full lockfile tree (npm, pnpm, yarn)
- Audit credentials — third-party scanner verdicts with trustedAuditIssuers + auditMaxAge
- SBOM — CycloneDX SBOM signed and bundled
Policy
npmvc-policy.json, written by install-hook --preset <name>:
{
"enforcement": "block",
"transitive": true,
"minAge": "7d",
"unattested": "warn",
"unattestedMinAge": "30d",
"trustedIssuers": ["https://npmvc.com/trust-root.json"],
"trustedAuditIssuers": [],
"auditMaxAge": "180d",
"attestationSources": ["local", "registry"],
"registry": "https://npmvc.com",
"allowPrivateRegistry": false,
"publisherContinuity": {
"required": true,
"onUnauthorizedChange": "block",
"pinned": { "express": "did🔑z6Mk..." }
},
"revocation": {
"required": true,
"registryUrl": "https://npmvc.com",
"maxCacheAge": "10m"
},
"lifecycleScripts": { "postInstall": "whitelisted", "whitelist": [] },
"waivers": []
}Set allowPrivateRegistry: true if you point registry at an internal
mirror or http:// host. By default the SSRF guards refuse private IPs.
CI/CD
Publish from GitHub Actions:
- name: Attest + Publish
env:
NPMVC_KEY: ${{ secrets.NPMVC_KEY }} # contents of ~/.npmvc/wallet/key.json
NPMVC_KEY_PASSPHRASE: ${{ secrets.NPMVC_KEY_PASSPHRASE }} # only if the key is encrypted
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
npm install -g @ajna-inc/npmvc
mkdir -p ~/.npmvc/wallet && echo "$NPMVC_KEY" > ~/.npmvc/wallet/key.json && chmod 600 ~/.npmvc/wallet/key.json
npm publish --access publicprepack runs npmvc attest automatically before npm packs the tarball.
See packages/github-action for a packaged
action with the same behaviour.
Key management
npmvc wallet encrypt --passphrase "..." # encrypt the in-use key at rest
npmvc wallet decrypt --passphrase "..." # undo (back to plaintext)
npmvc wallet export --passphrase "..." > key.enc # portable encrypted backup
npmvc wallet import --passphrase "..." --input key.enc # restore from backup
# Recovery (lost key, guardians configured)
npmvc wallet add-guardian --did did🔑z6MkFRIEND...
npmvc wallet set-threshold --threshold 2
npmvc wallet recover --old-did did🔑... --guardians did🔑a,did🔑b
npmvc wallet approve-recovery --request recovery-request.json
npmvc wallet apply-recovery --approvals approval-1.json,approval-2.json
# Rotation (did:webvh only)
npmvc wallet rotateCommands
| Command | Purpose |
|---|---|
init [--encrypt --passphrase ...] |
Create publisher DID |
attest [--registry URL] |
Sign attestations + optionally sync to registry |
verify |
Verify the installed dep tree |
install-hook [--preset strict|balanced|permissive] |
Add preinstall hook + policy |
policy init / policy show |
Manage the policy file |
register |
Register your DID on an npmvc registry |
audit publish / audit import |
Issue / import a third-party scanner credential |
credential revoke |
Revoke a credential on the registry |
credential handover |
Sign a maintainer-handover credential |
wallet encrypt / decrypt |
Toggle at-rest encryption of the key file |
wallet export / import |
Encrypted key backup |
wallet rotate (did:webvh) |
Rotate to the pre-committed backup key |
wallet add-guardian, set-threshold, guardians |
Recovery setup |
wallet recover, approve-recovery, apply-recovery |
Recovery flow |
anchor publish |
Build a transparency-log Merkle root |
Threat model and trust root
See SECURITY.md for the pinned community trust-root DID, rotation policy, and known limitations.
Packages in this repo
@ajna-inc/npmvc(the CLI) — rootpackage.json, sources insrc/packages/npmvc-web— the npmvc.com registry/UIpackages/github-action— GitHub Action wrapperpackages/verdaccio-plugin— early-stage stub, not for production use
License
Apache-2.0