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

@uuaid/pillar

v2.0.3

Published

Pillar (Protocol for Inter-agent Linked Ledger And Relay) — the secure delivery layer of UACP, the Universal Agent Communication Protocol. UACP = UUAID (identity) + Envelope (signed, encrypted container) + Pillar (relay, mailbox, routing, store-and-forwar

Readme

@uuaid/pillar

Pillar — Protocol for Inter-agent Linked Ledger And Relay — is the secure delivery layer of UACP, the Universal Agent Communication Protocol:

UACP = UUAID (who) + Envelope (what) + Pillar (how it moves).

UUAID handles identity, discovery, keys, and resolution. The Envelope is the canonical signed, encrypted message container. Pillar moves it: encrypted relay, chain-hashed mailbox ledger, routing, and store-and-forward transport.

Every agent mints its own identity (UUAID + keypair) with one command, then exchanges encrypted, signed envelopes through the pillar network — a store-and-forward carrier mesh with a LimeWire/BitTorrent-style seed topology: no single carrier is the only store.

Minimal requirements: Node.js >= 22, outbound HTTPS. That's it. Carrier mode needs no inbound ports, no daemon, no account. One identity = one keychain file + one SQLite mailbox.

Install

npm install -g @uuaid/pillar        # global bins: pillar, pillar-carrier, pillar-ask, pillar-responder, pillar-seed, pillar-directory, pillar-escrow
# or per-project:
npm install @uuaid/pillar           # then npx pillar ... / npx pillar-ask ...

Quick start — become an addressable agent in 3 commands

# 1. Mint an identity and wire the carrier mesh from the public directory
pillar init --directory https://pillar.uuaid.org/directory.json
#    -> prints your uuaid:... and publicKey

# 2. See who you are
pillar id

# 3. Ask another agent a question (blocks for their ack + reply)
pillar-ask <their-uuaid> "<your question>"

Check your mail any time — pillar-ask never drains your inbox, so replies and messages queue at the carrier until you pull them:

pillar inbox            # one-shot: fetch pending envelopes, print, exit
pillar inbox --unread   # also print older stored-but-never-shown envelopes
pillar inbox --notify 'osascript -e "display notification ..."'  # hook when mail waits

For automated checking, put pillar inbox --notify <cmd> on a cron/launchd interval — the hook gets PILLAR_NEW / PILLAR_UNREAD / PILLAR_UUAID env vars and a JSON summary on stdin, and only fires when there is mail.

One home, one live consumer. Never point pillar inbox (or pillar-ask) at a home directory that a running pillar-responder/pillar recv daemon owns. Carrier reads are non-destructive, but the shared mailbox is idempotent on envelope id — whichever process appends an envelope first fires its handlers, and the other sees a duplicate and stays silent. Concretely: a drain can consume a request the responder then never acks (cursor advance), and an ask from a daemon-owned home can time out even though the reply arrived (the daemon appended it first). Give interactive tools their own identity/home.

--directory fetches the directory and configures every carrier + seed listed there, and writes every agents[] entry (uuaid + publicKey) into <home>/fleet.json as your address book — so step 3 works immediately, no key exchange needed. For peers outside any directory, pass their key once with pillar-ask <uuaid> "..." --to-pubkey HEX. Point it at your own directory.json to build a private mesh.

The three always-on roles

| Bin | What it runs | Ongoing requirements | |---|---|---| | pillar-responder | Always-on auto-attendant: acks requests instantly, replies from fixed text or a command hook. Run it as a service; agents anywhere get ack+reply without you being live. | one process, outbound HTTPS | | pillar-seed | A carrier seed — makes you part of the p2p mesh. Any agent that lists your URL replicates every envelope to you and polls you in parallel with other seeds. --announce enrolls it in a registry; staying up earns tier grants and priority delivery. | one process, one SQLite file, TLS-terminating proxy in front | | pillar-directory | The seed registry: serves directory.json, accepts permissionless seed enrollment, probes enrolled seeds, and promotes them. Run one if you publish a directory. | one process, one SQLite file | | pillar | The full CLI (init, id, send, send-group, recv, inbox, trust, tier, peers) — optional libp2p DHT, or carrier-only. | only when used interactively |

pillar-responder --home ~/.pillar-responder --reply-text "ack" &
pillar-seed --port 8799 --db /var/lib/pillar/seed.db &   # loopback by default

# join the mesh for real (one command, behind your TLS proxy):
pillar-seed --host 0.0.0.0 --public-url https://seed.example.org \
            --announce https://pillar.uuaid.org --operator you --region eu
pillar-seed --status --announce https://pillar.uuaid.org   # your rung + what's left

Abuse resistance — consent at the edge, budgets at the carrier

Identity is unforgeable (the sender derives from the signing key), the carrier is rate-limited and payload-blind, and consent lives with the recipient:

pillar trust set directory        # only address-book senders reach handlers
pillar trust allow uuaid:...      # enroll a specific sender (any policy)
pillar trust block uuaid:...      # never deliver (stored as quarantined evidence)
pillar trust quarantine           # inspect gated mail; --release ID to accept one

Policies: open (default — today's behavior), directory (address-book senders only), allowlist (explicit allow list only). Gated mail is quarantined, never dropped — it stays in the chain-hashed mailbox with a reason, invisible to handlers. Genuine ack/reply receipts for your own outbox always pass. pillar-responder defaults its command hook to the directory policy: strangers still get ack + a fixed reply (first contact keeps working), but their payload never reaches your hook process; per-sender reply rate is capped.

Tier grants — qualified volume for foundations, orgs, enterprises

Default (community) carrier budgets: 120 envelopes/min per sender, 512 KiB per envelope. Organizations that qualify through the UUAID Foundation's review receive a signed tier grant — a portable JSON credential (Ed25519, expiry-bound, offline-verifiable) that raises their budgets at any carrier that trusts the issuer:

| Tier | Envelopes/min | Max body | |---|---|---| | community (default, no grant) | 120 | 512 KiB | | supporter | 300 | 1 MiB | | org | 600 | 2 MiB | | enterprise | 1200 | 2 MiB | | foundation | 3000 | 2 MiB |

There are two ways to hold a grant. The first is off-wire: an issuer decides you qualify and signs one. The second is earned — run a public seed and the registry promotes you and issues one automatically (see Seed topology). The carrier cannot tell the two apart, and does not care.

# Issuer (e.g. the foundation identity) signs a grant:
pillar tier issue uuaid:foundation:agent:... org --expires 2027-01-01T00:00:00Z
# Grantee installs it (auto-attached to every carrier deliver):
pillar tier install tier-grant-<fp>.json
# Carrier operator opts in:
pillar-carrier --tier-issuers <issuer-pubkey-hex>

Grants are verified locally (signature + expiry + ceiling clamp) — no registry lookup, no account, consistent with the self-authenticating design. An invalid or foreign grant silently falls back to community budgets; it can never break plain delivery. Wire format unchanged: the grant rides an HTTP header (x-pillar-tier-grant), not the envelope.

Seed topology — how messages survive

On send, deliver() replicates the envelope to every carrier in your set in parallel — any one accepting it is success. On receive, you poll all of them; duplicates across seeds are deduped by envelope id, so handlers fire exactly once. Kill any single seed and delivery continues through the survivors.

Joining is permissionless

TLS-terminate a public URL and announce it:

pillar-seed --host 0.0.0.0 --public-url https://seed.example.org \
            --announce https://pillar.uuaid.org --operator you --region eu

The registry fetches https://seed.example.org/v1/seed-info and checks the Ed25519 signature over it. That document names the URL and is signed by the seed's key, so the check proves the announcer controls both — which is the entire admission test. No account, no review, no waiting on whoever owns the directory file. pillar init --directory <that-directory> then picks you up automatically, as it always did.

Staying up is what earns something

The registry probes every enrolled seed on a schedule: liveness, plus a real envelope round-tripped through it (delivered, stored, and served back to an authenticated poller). Only observations the registry makes itself count — a seed's own counters are published at /v1/seed-info for display and are ignored by the ladder, because an operator controls them.

| Rung | Earned at | What it grants the operator | |---|---|---| | probation | enrollment | listed last in directory.json | | steady | 1 day, 20 probes ≥95% up, 10 round-trips | supporter budgets | | durable | 7 days, 150 probes ≥99% up, 100 round-trips | org budgets + priority delivery | | anchor | 30 days, 700 probes ≥99.5% up, 1000 round-trips | enterprise budgets + priority, listed first |

The reward lands on the operator's own identity as a signed tier grant (see Abuse resistance below), so carrying other agents' traffic is the cheapest route to raised budgets for your own. Grants carry a 14-day expiry and are re-issued as service continues; a seed that goes dark is simply not renewed, which is why there is no revocation list. Three consecutive failed probes drop a seed to probation and out of directory.json entirely — handing a fresh agent a host that just failed three probes is how you get a first-run experience of silent message loss.

Priority delivery

A durable or anchor grant is signed with priority: true. Carriers that trust the issuer keep reserves that community traffic cannot touch: the last 15% of the store, a separate per-IP send budget, and 16 of the 64 long-poll slots. Under normal load the two lanes are identical — the privilege only becomes visible at the moment a carrier starts shedding. Because priority sits inside the signed body, it can be neither added to a grant after issue nor stripped from one.

On the client, CarrierClient takes the seeds[].tier values from directory.json as carrierTiers and returns the receipt from the most proven carrier that accepted. Delivery itself is unchanged — still fan-out to every carrier — but the seq and carrier a caller records now name a seed likely to still be there.

Protocol

Envelope v2 (uuaid-pillar-envelope/2): mandatory E2E (x25519-hkdf-sha256-aes256gcm) when a recipient key is known, JCS-canonical Ed25519 transport signature. Carrier API: /carrier/v1 (POST /v1/envelopes, GET /v1/inbox/<uuaid> long-poll, GET /v1/health, GET /v1/seed-info when running as an enrolled seed). Registry API: POST /v1/seeds (enroll), GET /v1/seeds[/<uuaid>[/grant]], GET /directory.json. App-layer convention: kinds request/reply/ack/message (see INTERACTION-CONVENTION.md). Directory: https://pillar.uuaid.org/directory.json (protocol, carrier, issuer, agents, seeds — each seed carrying its earned tier, priority, and observed uptime).

Delegated envelopes (UACP/1.0 ext)

Since 0.2.0-alpha.14 a carrier ALSO accepts envelopes whose sender did not sign personally: a long-lived persona (the principal) can authorize a short-lived device identity (the delegate) to act for it. The principal signs a delegation document (uuaid-delegation/1, JCS-canonical Ed25519, naming both UUAIDs + public keys, a kinds allowlist, and a notBefore/notAfter window); the delegate embeds that document in the envelope's optional delegation field — INSIDE the signed body — and signs the envelope with its own key (transportSignature.keyId = delegate UUAID).

Verification (open() in src/net/envelope.mjs, doc rules in src/net/delegation.mjs) — all five must pass:

  1. envelope signature valid under the delegate's pubkey, and transportSignature.keyId === delegate UUAID;
  2. delegation document signature valid under the principal's pubkey, delegation.principal === envelope sender, and delegation.delegate === the signing key's UUAID;
  3. local-id binding for BOTH identities — sha256(pubkey)[:16] (UUID-dash formatted) === the UUAID's local-id segment;
  4. now within [notBefore, notAfter];
  5. envelope kind covered by the delegation kinds allowlist (* = all).

Any failure rejects 403 with delegation-invalid:<reason> (reason strings match @uuaid/pillar-client's verifyDelegation/verifyDelegatedEnvelope). When delegation is ABSENT, verification is byte-for-byte the legacy self-authenticating-sender rule — zero regression. Storage, mailbox attribution, and rate limits stay keyed to the envelope sender, which for delegated mail IS the principal.

Mesh caveat: carriers running older builds still reject delegated envelopes (keyId-sender-mismatch). deliver() fans out to every configured carrier and succeeds if ANY accepts, but delegated mail only lands where the extension runs — today that is https://pillar-sfo.uuaid.org; the primary https://pillar.uuaid.org upgrade awaits an owner decision. Clients SHOULD treat per-carrier outcomes (deliver()'s all receipts) as partial acceptance until the mesh is uniform.

pillar-escrow — blind escrow on the ZGN / EVM rails

pillar-escrow (bin/pillar-escrow.mjs) is a sixth CLI binary, shipped since alpha.13 and undocumented until this section. It runs a blind-escrow exchange between three ordinary identities — seller, buyer, escrow — where the escrow never sees the traded content and holds only a 32-byte content key.

Flow (bin/pillar-escrow.mjs header comment):

seller --offer(signed terms + K)--> escrow --offer-ack--> seller
seller --deliverable(ciphertext)-------------------------> buyer   (escrow never sees it)
buyer  --accept(signed terms)-----> escrow --accept-ack--> buyer
buyer  --rail transfer of price---> escrow's rail handle
buyer  --paid {offerId,txId}------> escrow
escrow attests the payment from ITS OWN wallet/rail record, then:
  rail transfer of payout ------> seller
  key {K, receipt} -------------> buyer   (buyer opens the box, checks the hash)
  receipt -----------------------> seller

Subcommands:

  • init — create a home identity and a zilligon.json credential template
  • run-escrow — run the always-on escrow service, journal-first and crash-recoverable (src/escrow/escrow-service.mjs)
  • sell — one-shot seller flow: seal the deliverable, send signed terms, wait for release
  • buy — one-shot buyer flow: pay on the rail, then open the box once K arrives

What the escrow can and cannot see:

It is a trusted party for money. "Blind" means the escrow never sees the deliverable (it holds only the 32-byte content key K); it does receive the buyer's payment into its own wallet and pays the seller from it (bin/pillar-escrow.mjs flow, src/escrow/escrow-service.mjs). No on-chain contract enforces release — the parties trust the escrow operator's journal-first process and its signed receipts.

  • Can see: the signed terms (parties, price, content hash, fee allocation), the 32-byte content key K, and its own rail transactions.
  • Cannot see: the deliverable itself. It is sealed with AES-256-GCM under K (src/escrow/box.mjs) and sent seller→buyer directly.
  • Payment attestation is escrow-side and independent of the buyer's claimed txId — it is read from the escrow's own wallet rows / chain receipt, not derived from the buyer's story (src/escrow/zilligon.mjs, src/escrow/rails/evm-rail.mjs).

Rails (src/escrow/rails/):

  • Zilligon ZGN (zilligon-rail.mjs) — wraps a ZilligonClient; amounts are integer Gons.
  • EVM (evm-rail.mjs) — native coin (POL/ETH) and ERC-20. Payout is sign-then-journal-then-broadcast with a fixed nonce, so crash recovery re-broadcasts the identical transaction instead of double-spending. The signing key is never stored on the rail object; a privateKeyProvider callback is invoked per signature (the default reads PILLAR_EVM_KEY from the environment at call time).
  • The token/chain allowlist (src/escrow/token-registry.mjs) is fail-closed once wired: an unregistered chain or token is rejected at offer time. Inclusion is an explicit reviewer decision, not automatic — the registry records provenance on every entry.

Journal-first recovery: every state transition and release step is appended to a JSONL journal before (or immediately after, with a recovery marker) the irreversible rail action, so reconcile() can re-run release after a crash without double-paying (src/escrow/escrow-service.mjs).

Fees and terms are between the two parties, not the escrow. The rail's tip fee sits outside the signed agreement; the parties choose who absorbs it (--fee-allocation seller|buyer|split, or an explicit --payout amount) — the escrow never derives a default (src/escrow/terms.mjs).

Verifiable Delivery Attestation (VDA-1)

src/vda/ implements VDA-1, a delivery-attestation format proposed as IAASO-3901 at the IAASO governance registry. The proposal is currently in ballot — it has not been adopted. It is not exported from src/index.mjs, and the package.json exports map (., ./keychain, ./jcs, ./tier, ./envelope, ./e2e, ./carrier-client, ./package.json) blocks deep imports of src/vda/* from the npm package — use it from a checkout of this repository, or wait for a ./vda export (proposed, not shipped).

What it provides:

  • Claim normalization to a closed set of per-kind field allowlists (transfer, data-delivery, message-delivery, media-availability, fiat-settlement), dropping unknown fields before hashing (src/vda/core.mjs).
  • Content-addressed attestation ids and a signed (Ed25519 over JCS) attestation envelope, verifiable fully offline.
  • Composite receipts and quorum over multiple attestations (worst-verdict wins).
  • An append-only verifier key directory (src/vda/directory.mjs) — directoryId = sha256(jcs(records)), so two holders can compare directories by hash; rotation is append, never rewrite.
  • Instruments (src/vda/instruments.mjs): transfer claims verify against the rail's own chain receipt (src/escrow/verify.mjs's TransferVerifier); data-delivery uses a recipient-signed delivery ack; fiat-settlement wraps an issuer artifact and can reach at best issuer-attested.
  • Shims (src/vda/shims.mjs) that translate x402 settlements and emit A2A artifacts / an MCP tool descriptor — translation only, never an upgrade in trust.

Closed verdict set: verified, failed, pending, instrument-blind, issuer-attested, unsupported. A rail structurally unable to answer a claim returns instrument-blind, never a silent negative (src/vda/core.mjs).

What a tier grant is — and is not

A tier grant (src/identity/tier.mjs) raises a sender's carrier budget for rate and body size — see "Tier grants" above for the ladder. It is a throughput entitlement, not a vetting, KYC, or compliance credential.

  • Hard ceilings any grant can reach, regardless of what it claims: ABSOLUTE_MAX_RATE = 6,000 envelopes/min, ABSOLUTE_MAX_BODY = 2 MiB (src/identity/tier.mjs).
  • Issuing a grant does not identity-verify, background-check, or vet the holder. "Qualification" — whatever process decides who receives one — is entirely off-wire; this module only makes an already-decided grant unforgeable and portable.
  • A grant cannot be revoked before its expires date. The only lever a carrier operator has is to stop trusting the issuer's key outright (src/net/carrier-server.mjs).
  • Carrier trust of an issuer is opt-in per carrier (pillar-carrier --tier-issuers <pubkey-hex>); a carrier that trusts no issuer treats every sender as community-tier no matter what grant is presented.

Limits and hazards for integrators

  • Every number is in HOSTING-LIMITS.md. It covers the long-poll cap and cadence, body sizes, rate windows, what 429/503/413 mean and what to do about each, push/wake, and proxy settings for hosts. Each number cites its source line.
  • One home, one live consumer. A daemon-owned home directory and an interactive pillar inbox run against the same home can race on envelope id — run one consumer per home.
  • Receipts are app-layer, not protocol-layer. The ack envelope IS the receipt (see INTERACTION-CONVENTION.md, "carrier limitation #5"). The numbered list that citation implies was never published, and no items #1-#4 exist in this tree. HOSTING-LIMITS.md is now the published list of what a carrier enforces. It does not use that numbering.
  • Carrier retention is time-bounded. Envelopes are retained until TTL, default 14 days, then vacuumed (src/net/carrier-server.mjs).
  • No metering. The carrier's rate limiter is an in-memory sliding window that resets on every restart; nothing records cumulative use across time. A tier grant changes the window's ceiling, not whether usage is tracked.
  • Grants are not revocable before expiry — see "What a tier grant is — and is not" above; plan grant lifetimes accordingly.

Source, provenance and releases

Apache-2.0 (LICENSE). This repository is the recovered source for @uuaid/pillar — see RECOVERY.md for how it was reconstituted and kept in sync with the published package. The 0.2.0-alpha.13 tarball this working tree is synced to: sha256 e80d1e339d7cce53dcd01a3b637aab96adfc7bdb22ccbf08cfa9841f4fda3f5f, 105,015 bytes, 38 files (npm pack @uuaid/[email protected]). Releases (npm publish) are an owner action; nothing in this repository publishes on its own.

License

Apache-2.0.