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

@ours.network/notifications

v0.1.1

Published

ours.network Notifications-as-a-Service — a2a_notifications service packet + WebPush daemon, with a start/stop/status/install-service CLI (ours-notify). Self-provisions identity + VAPID; runs on any host, point DNS at the discovery port.

Readme

ours-notifications

Reach a person — or their agent — even when their app, tab, or daemon is closed. Give anything on the network a way to send real browser push notifications, so an agent can get someone's attention out-of-band instead of hoping they're watching.

The ours.network Notifications-as-a-Service node: an always-online packet

  • Node daemon that accepts token-authorized notification posts from anyone on the network and pushes them to the recipient's browser(s) via WebPush — even while the recipient's own agent/daemon/tab is not running.

The protocol surface lives in the shared core (ours-mufl-core/a2a_notifications.mm, contract: ours-mufl-core/NOTIFICATIONS_CONTRACT.md). This repo is the reference service implementation: the packet wiring, persistence, WebPush egress, a VAPID key tool, a browser demo, and integration tests.

⚠️ Trust model (v1 — read before operating or using an instance)

The service reads every notification payload (no E2E). Payloads are encrypted in transit (wire envelopes; WebPush aes128gcm) but the service node decrypts, stores, and forwards them in plaintext. Never put secrets in a notification payload you would not show the service operator.

v1 has no anti-spam: anyone holding your token can notify you; rotate the token (notify_rotate_token) to cut them off. Rotation invalidates the old handout instantly; you then redistribute the new one.

Install & run as a service (ours-notify)

The daemon ships as an installable package with a full CLI that mirrors ours-mcp / ours-tg-connector. It self-provisions its identity (identity.key → a stable cid across restarts) and a VAPID keypair on first start, so a fresh install just works — point a DNS name at the discovery port and you have a notifications service.

npm i -g @ours.network/notifications          # installs the `ours-notify` bin

# configure (env, or a config.json — see below). BROKER_URL is the only required field.
export BROKER_URL=ws://broker.example.net:9000    # your ADAPT broker
export STATE_DIR=~/.ours-notifications            # default; identity + VAPID + state live here
export DISCOVERY_PORT=8890                         # default; the HTTP /v1/discovery port
export DISCOVERY_HOST=0.0.0.0                      # bind publicly when behind DNS/a proxy

ours-notify start        # spawn the background daemon (self-provisions on first run)
ours-notify status       # running? port, cid, broker, state dir, version
ours-notify stop         # graceful stop
ours-notify restart

# boot-persistent service (systemd user unit + linger on Linux; launchd on macOS):
ours-notify install-service     # bakes the resolved config into the unit, enables + starts it
ours-notify uninstall-service

Point DNS at the host and expose DISCOVERY_PORT: clients fetch the service cid

  • VAPID public key from https://<your-domain>/v1/discovery at runtime, so a client (e.g. the messenger panel) needs no rebuild when you deploy or rotate.

Config precedence (per field): env > config.json > default. config.json lives at $OURS_NOTIFY_CONFIG, else <HOME>/.ours-notifications/config.json:

{ "brokerUrl": "ws://broker.example.net:9000", "discoveryPort": 8890, "discoveryHost": "0.0.0.0" }

Self-hosting

You can run this service yourself and point the ours control panel at it — the panel's default stays the hosted notify.ours.network, self-hosting is the opt-out. Full walkthrough (VPS → TLS → verify → panel bind): docs/SELF-HOSTING.md.

Architecture

 sender S ──bare signed send (token authz)──▶ ┌────────────────────────────┐
                                              │ service packet (MUFL)      │
 recipient R ◀─encrypted channel (contacts)─▶ │  a2a_notifications service │
   register / bindings / rotate / mark_read   │  half: validate + resolve  │
                                              └───────────┬────────────────┘
                                                          │ $notify_agent events
                                                          ▼
                                              ┌────────────────────────────┐
                                              │ daemon (Node, this repo)   │
                                              │  notifications.json log    │
                                              │  web-push VAPID egress ────┼──▶ browser push services
                                              └────────────────────────────┘
  • The packet validates registrations/tokens and hands (notification, bindings) to the daemon; storage and HTTP stay app-side.
  • The recipient↔service surface rides the encrypted channel (they are contacts via the normal invite flow). The sender needs no contact and no channel: the handout blob (service cid + per-contact scoped token) is everything.
  • Identity + state survive restarts: identity.key (0600, the packet's Serialize-hex sign secret, reinjected via __init reseed) and state_data.bin (written on every $save_state).
  • The daemon serves two surfaces on DISCOVERY_PORT (default 8890): GET /v1/discovery (service cid + VAPID public key) and the /v1/presence WebSocket. A client opens /v1/presence while its PWA is foreground so the service can suppress a redundant WebPush while a live client is already showing the conversation; closing/backgrounding drops the socket and restores push delivery.

Must sit behind TLS. /v1/presence authenticates each socket with the client's own WebPush auth secret, presented in the first frame. That credential (and all discovery traffic) crosses the wire in plaintext, so in any real deployment the daemon must be fronted by a TLS-terminating reverse proxy (wss:// / https://) — never expose DISCOVERY_PORT directly to the network.

Environment

| var | meaning | |---|---| | BROKER_URL | ADAPT broker websocket, e.g. ws://127.0.0.1:9000 (required; env or config.json) | | STATE_DIR | daemon state: identity.key, state_data.bin, notifications.json, vapid.* (default <HOME>/.ours-notifications) | | VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY | inline VAPID keypair (or *_FILE variants). Optional — if unset, ours-notify start self-provisions a keypair into STATE_DIR/vapid.{public,private}. The private key never enters packet state. | | VAPID_SUBJECT | mailto: or URL contact for push services (default mailto:[email protected]) | | UNIT_DIR | compiled packet dir (default mufl_code/) | | PUSH_DISABLED | 1 = log instead of pushing (dev) | | PUSH_TLS_INSECURE | 1 = accept self-signed push endpoints (mock tests / lab ONLY) | | DISCOVERY_PORT | port for the GET /v1/discovery HTTP endpoint (CLI default 8890; running dist/daemon.js directly leaves it disabled unless set) | | DISCOVERY_HOST | bind address for the discovery server (default 127.0.0.1; use 0.0.0.0 behind DNS/a proxy) | | OURS_NOTIFY_CONFIG | path to config.json (default <HOME>/.ours-notifications/config.json) |

Run (local or any VPS — identical steps; WebPush needs no vendor accounts)

npm install
git submodule update --init
ADAPT_TOOLKIT=/path/to/adapt ./scripts/compile-mufl.sh
node scripts/gen-vapid.mjs ./vapid                     # once per instance
npm run build

# a broker (local dev; production points BROKER_URL at a deployed broker)
node scripts/dev-broker.mjs --host 127.0.0.1 --port 9000 --test_mode &

BROKER_URL=ws://127.0.0.1:9000 STATE_DIR=./state \
VAPID_PUBLIC_KEY=$(cat vapid/vapid.public) \
VAPID_PRIVATE_KEY=$(cat vapid/vapid.private) \
node dist/daemon.js

The daemon speaks JSON-lines on stdin/stdout: {"cmd":"invite","name":"alice"} → invite blob (hex) for a recipient; {"cmd":"contacts"}, {"cmd":"notifications"}, {"cmd":"status"}, {"cmd":"export_vis"}.

Browser demo (the human-visible proof)

  1. Run broker + daemon (above), then node demo/serve.mjs 8080.
  2. Register a recipient identity and connect it to the service:
    echo '{"cmd":"invite","name":"demo-recipient"}' | # or drive the daemon stdin directly
    node scripts/drive.mjs register --broker ws://127.0.0.1:9000 --state ./demo-recipient \
         --invite <invite-hex-file>
  3. Open http://localhost:8080/, paste vapid/vapid.public, Subscribe, copy the binding JSON to a file, then:
    node scripts/drive.mjs update-bindings --broker ws://127.0.0.1:9000 \
         --state ./demo-recipient --binding binding.json
    node scripts/drive.mjs export-address --broker ws://127.0.0.1:9000 \
         --state ./demo-recipient --out handout.hex
  4. From a second, never-connected identity, send:
    node scripts/drive.mjs send --broker ws://127.0.0.1:9000 --state ./demo-sender \
         --address handout.hex --payload "hello from the demo"
    The notification pops in the browser — close the tab first to prove the out-of-band wake-up.

Tests

npm test   # daemon boot/persistence/VAPID hygiene + mock-push e2e (Flow A→B→C + rejections)

The e2e test runs the full flow against a dev broker and a local HTTPS mock push endpoint: register → browser-style subscription keys → non-contact sender post → ONE aes128gcm WebPush POST with VAPID headers → notifications.json unread → mark_read flips it → rotated-out and unregistered handouts are rejected with no push and no log entry.

Operational notes

  • The notification log is unbounded in v1 (no GC) — rotate/purge notifications.json operationally if needed.
  • WebPush 404/410/5xx are logged and skipped (no binding auto-prune in v1).
  • Duplicate posts are delivered twice (no dedup in v1).

Learn more

  • How it works — the protocol, in depth: the shared agent-to-agent core and wire format (including the notifications contract) is documented in ours-mufl-core.
  • The whole project: ours.network · umbrella repo

Support ours.network

ours.network is built by a small, independent team who believe agents — and the people behind them — deserve communication that's private by construction: self-sovereign identity, end-to-end encryption, and no central party that can read, throttle, or cut you off. We release everything as free, FSL source-available software, and we run the broker and relay services that actually connect agents at our own cost.

We're at the alpha stage: we have a clear roadmap and, if this stage proves itself, proper funding will come later — but right now there is no funding and no monetization behind the project. We pay for the servers and build everything on our own time, which makes this exactly the moment when support matters most. Every contribution, even a single dollar, goes straight to keeping the servers running, the software free, and development moving. If ours.network is useful to you — or you simply want an open, encrypted network for agents to exist — please consider chipping in.

Like it? Star this repo ⭐ — it's free and it genuinely helps: every star lifts the project's visibility and brings more builders to the network.

→ https://github.com/adapt-toolkit/ours-donate

Thank you for helping keep it free, open, and alive.

Licence, status & warranty

Alpha software. ours-notifications is part of ours.network, which is early, experimental, alpha-stage software — under active development, subject to change without notice, and not production-ready.

No warranty / not security-audited. ours.network has not been independently security-audited. It is provided "as is", without warranty of any kind, and you use it at your own risk. See LICENSE and SECURITY.md.

ours.network is owned and licensed by Adapt Framework Solutions Ltd. It is released under the Functional Source License, Version 1.1 (FSL-1.1-Apache-2.0)source-available, not open source during the FSL period. Each release converts to Apache 2.0 two years after it is published.

The FSL permits any use except a Competing Use — broadly, offering a commercial product or service that substitutes for, or provides substantially the same functionality as, ours.network. Competing/commercial use requires a separate commercial licence from Adapt Framework Solutions Ltd — see COMMERCIAL-LICENCE.md (contact: [email protected]).

Built on Adapt. ours.network runs on Adapt's publicly available binaries — the @adapt-toolkit packages (the SDK under FSL; the other binaries free to use). Adapt's own source code (its C++ core) is not open yet — it will be opened later.

Third-party notices: THIRD_PARTY_NOTICES.md.

Copyright 2026 Adapt Framework Solutions Ltd.