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

@veilgate/node

v1.1.3

Published

Node.js SDK for VeilGate — attach bearer tokens and sign HMAC requests in server-to-server calls

Downloads

597

Readme

@veilgate/node

Node.js SDK for VeilGate. Three responsibilities:

  1. Outgoing auth — attach bearer tokens or HMAC-sign server-to-server requests.
  2. Decoy response headers — inject tarpit breadcrumbs into your API's outgoing responses so agents probing the API via raw HTTP find bait paths instead of real endpoints.
  3. Signature verification — validate inbound HMAC signatures in tests or custom middleware.

Install

npm install @veilgate/node

Requires Node.js ≥ 18.

Usage

Bearer mode

import { bearerFetch } from "@veilgate/node";

const apiFetch = bearerFetch("vg_live_abc123");
const resp = await apiFetch("https://api.example.com/widgets");

Custom header or scheme:

const apiFetch = bearerFetch({ token: "abc123", header: "X-Api-Key", scheme: "" });

HMAC mode

import { hmacFetch } from "@veilgate/node";

const apiFetch = hmacFetch({
  clientId: "payments",
  secret: process.env.VG_SECRET!,
});

const resp = await apiFetch("https://api.example.com/charge", {
  method: "POST",
  body: JSON.stringify({ amount: 100 }),
  headers: { "Content-Type": "application/json" },
});

Decoy response middleware

Add tarpit breadcrumbs to every outgoing API response. Compatible with Express, Fastify, and raw Node http.Server — anything with res.setHeader().

import { decoyMiddleware } from "@veilgate/node";

// Express
const decoys = decoyMiddleware({ baseURL: "https://api.example.com" });
app.use(decoys);

// Runtime controls — no need to recreate the middleware
decoys.setEnabled(false);           // disable (e.g. internal health-check routes)
decoys.setEnabled(true);            // re-enable
decoys.update({ count: 5 });        // inject more paths per response
decoys.update({ baseURL: "https://new-api.example.com" }); // switch server (clears cache)
decoys.update({ paths: [          // static override — skips .well-known discovery
  { path: "/actuator/env", service: "spring-actuator" },
  { path: "/v1/secret/data/prod", service: "vault" },
]});

Agents probing the API will see response headers like:

Link: </actuator/env>; rel="help", </.env.local>; rel="related"
X-Api-Documentation: /swagger-ui.html
X-Debug-Endpoint: /api/internal/debug

Low-level decoy helpers

import { fetchDecoyPaths, decoyResponseHeaders } from "@veilgate/node";

// Fetch tarpit.paths from .well-known (60 s cache)
const paths = await fetchDecoyPaths("https://api.example.com");

// Build a header map from any path list
const headers = decoyResponseHeaders(paths, { count: 3 });
// → { Link: "...", "X-Api-Documentation": "...", "X-Debug-Endpoint": "..." }

// Attach to a raw Node response
for (const [name, value] of Object.entries(headers)) {
  res.setHeader(name, value);
}

API

bearerFetch(tokenOrOpts, fetchImpl?)

Returns a fetch-compatible function with a static bearer token attached. Does not override an existing Authorization header set by the caller.

| Option | Type | Default | Description | |--------|------|---------|-------------| | token | string | — | Token value | | header | string | "Authorization" | Header name | | scheme | string | "Bearer" | Scheme prefix. Pass "" for raw-token mode |

hmacFetch(opts, fetchImpl?)

Returns a fetch-compatible function that signs every request with HMAC-SHA256.

| Option | Type | Default | Description | |--------|------|---------|-------------| | clientId | string | — | Sent in X-Veilgate-Client | | secret | string | — | Shared HMAC secret | | signatureHeader | string | "X-Veilgate-Signature" | Override signature header | | clientHeader | string | "X-Veilgate-Client" | Override client-id header | | replayWindow | number | 300 | Replay protection window in seconds |

fetchDecoyPaths(baseURL?, fetchImpl?)

Fetches /__veilgate/.well-known and returns the tarpit.paths array. Results are cached for 60 seconds matching the server's Cache-Control: max-age=60. Returns an empty array on any error.

decoyResponseHeaders(paths, opts?)

Pure function. Builds a Record<string, string> of HTTP response headers from a path list. Headers produced:

| Header | Condition | |--------|-----------| | Link | Always (when linkHeader !== false). RFC 8288 rel types: help, related, about, describedby | | X-Api-Documentation | When a path matching openapi/swagger is in the picked set | | X-Debug-Endpoint | When a path matching debug/internal is in the picked set |

| Option | Type | Default | Description | |--------|------|---------|-------------| | count | number | 3 | Paths to inject | | linkHeader | boolean | true | Emit Link header | | serviceHeaders | boolean | true | Emit X-Api-Documentation / X-Debug-Endpoint |

decoyMiddleware(opts?)

Returns a DecoyMiddlewareFn — callable as a standard middleware and extended with runtime controls.

| Option | Type | Default | Description | |--------|------|---------|-------------| | baseURL | string | "" | VeilGate server for .well-known discovery | | paths | TarpitPathEntry[] | — | Static override; skips discovery | | count | number | 3 | Paths per response | | linkHeader | boolean | true | Emit Link header | | serviceHeaders | boolean | true | Emit service-hinting headers | | fetchImpl | typeof fetch | globalThis.fetch | Override for tests |

Runtime methods on the returned function:

| Method | Description | |--------|-------------| | .setEnabled(boolean) | Enable or disable header injection without recreating the middleware | | .update(Partial<DecoyOptions>) | Merge new options; clears discovery cache when baseURL or paths changes |

signRequest(secret, method, path, body?, timestamp?)

Compute a t=<ts>,v1=<mac> signature string directly.

signHeaders(opts, method, path, body?, timestamp?)

Returns a { [header]: value } object ready to spread into your request headers.

verifySignature(signature, secret, method, path, body?, opts?)

Verify an inbound HMAC signature. Returns true only when the MAC is valid and the timestamp is within the replay window. Uses timingSafeEqual internally.

Signature Format

Canonical: <unix-ts>.<METHOD>.<path+query>.<hex(sha256(body))>
Signature: t=<ts>,v1=<hex(HMAC-SHA256(secret, canonical))>

License

MIT