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

@setu-ts/diagnostics-plugin

v0.11.0

Published

Authenticated local diagnostics connector: signed loopback polling for the devtool

Readme

@setu-ts/diagnostics-plugin

The authenticated local diagnostics connector (M98b): connects a native devtool client to the kernel diagnostics (M98a) over a separate, runtime-owned authenticated IPv4 loopback HTTP listener. Deno and Node, with bounded polling only. No browser UI, no application-data reads, no application-control commands, and authentication is independent of any devtool subscription.

Trust model — read this first

  • Loopback is not authentication. The HMAC-SHA-256 signed protocol is. Every request and response byte is MAC-verified with a fresh per-launch session key.
  • Loopback is not encryption. A privileged local process can sniff authenticated bytes. Remote tunnels, shared untrusted hosts, and production use are outside this transport's threat model.
  • No environment fallback. Importing the package, registering unrelated plugins, or setting an environment variable never exposes an endpoint. Activation requires explicit plugin options.
  • Trusted application code and installed in-process plugins already run with application privileges; this is not a sandbox against a compromised process.

Installation

import { DiagnosticsPlugin } from '@setu-ts/diagnostics-plugin';

No third-party dependency. The listener socket is owned by @setu-ts/runtime (RuntimePlugin is a required dependency of every application and now provides CAPABILITIES.LOCAL_DIAGNOSTICS_LISTENER).

Per-session rate buckets are swept on authenticated promotion using a doubling threshold starting at 64 sessions. A bucket is discarded only after it has refilled to its full burst; a drained or partially refilled bucket keeps its budget.

Pairing

The trusted native launcher generates a fresh 32-byte session key and a 16-byte session ID per launch and passes them to the application's composition in memory (its environment handoff is the launcher's trust boundary; application subprocesses must not inherit these values). Sharing one pair across applications is unsupported. The plugin copies the key into a non-extractable Web Crypto HMAC key and zeroes its temporary copy.

Usage

import { createApplication } from '@setu-ts/kernel';
import { RuntimePlugin } from '@setu-ts/runtime';
import { DiagnosticsPlugin } from '@setu-ts/diagnostics-plugin';

// Fresh per-launch credentials, generated here for the example; in a real
// launch the trusted native launcher supplies them in memory.
const sessionId = Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) =>
  b.toString(16).padStart(2, '0'),
).join('');
const sessionKey = crypto.getRandomValues(new Uint8Array(32));

const diagnostics = DiagnosticsPlugin({
  enabled: true, // explicit opt-in; false/omitted refuses activation
  port: 4919, // 1024–65535, IPv4 loopback only, no auto-selection
  sessionId, // 16 random bytes as 32 lowercase hex, per launch
  sessionKey, // 32 random bytes, per launch
  ttlMs: 900_000, // optional; 15 minutes default, max 1 hour
  maxSessionLifetimeMs: 28_800_000, // optional renewal cap; max 12 hours awake time
});

const app = createApplication({
  plugins: [RuntimePlugin(), diagnostics],
  diagnostics: {}, // M98a kernel diagnostics must be enabled
});
await app.start();

// Later, without stopping the application:
await diagnostics.revoke();

Activation refusals are startup failures: missing kernel diagnostics, an unsupported runtime, an invalid port, or invalid credentials. Port conflicts fail closed — no scan, no fallback address.

Development-only composition

enabled is an acknowledgement, not a toggle. There is no disabled mode: enabled: false never activated anything, it is refused at composition time. So the obvious line for "run it outside production only" —

DiagnosticsPlugin({ enabled: !isProduction, … })

— would not give you an inert connector in production. It would give you an application that throws at composition and never boots. enabled is typed as the literal true so that shape is a compile error rather than a production outage. Decide by inclusion.

The decision has to be made at createApplication() time — the kernel's collector is built in the constructor and diagnostics is a construction option — so the cleanest shape is a development-only entry point that production never imports:

import type { IApplication, IPlugin } from '@setu-ts/common';
import { createApplication, type KernelDiagnosticsOptions } from '@setu-ts/kernel';
import { RuntimePlugin } from '@setu-ts/runtime';
import { DiagnosticsPlugin } from '@setu-ts/diagnostics-plugin';

// setu.config.ts — no devtool import anywhere in the production graph.
//
// The composition is the SECOND parameter deliberately — and it is spelled
// `devtool`, because this is the exact shape `setu new --devtool` and
// `setu devtool enable` emit since M98c. `setu commands` builds the
// application to discover plugin-contributed verbs, and it calls this factory
// with its own inert discovery env as the FIRST positional argument on every
// target (`app-loader.ts`) — so a single-parameter `createApp(extra?)` would
// receive that proxy as `extra` and throw on the spread below.
export function createApp(
  _env?: Readonly<Record<string, unknown>>,
  devtool?: { plugins?: readonly IPlugin[]; diagnostics?: KernelDiagnosticsOptions },
): IApplication {
  return createApplication({
    plugins: [RuntimePlugin(), ...(devtool?.plugins ?? [])],
    ...(devtool?.diagnostics !== undefined ? { diagnostics: devtool.diagnostics } : {}),
  });
}

// main.ts — production. Never imports @setu-ts/diagnostics-plugin.
export const production: IApplication = createApp();

// main.dev.ts — the ONLY module that imports the connector.
const sessionId = Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) =>
  b.toString(16).padStart(2, '0'),
).join('');
const sessionKey = crypto.getRandomValues(new Uint8Array(32));

export const development: IApplication = createApp(undefined, {
  plugins: [DiagnosticsPlugin({ enabled: true, port: 4919, sessionId, sessionKey })],
  diagnostics: {},
});

That makes exclusion a property of the build rather than of a runtime branch: the production entry cannot enable the connector, because it never imports it.

Credentials come from the trusted launcher through the child process environment (see Pairing); the plugin reads no environment variable itself, so nothing auto-enables. setu new --devtool and setu devtool enable emit exactly this composition — the development entry, its dev task, and a check task that reaches main.dev.ts.

Optional hardening: a scoped network grant

A generated project's start task carries a BARE --allow-net. Scoping it to the application port is OPTIONAL hardening for a project with no egress — not a default, and not a guarantee you already have. On Deno 2.9.6 an allowlist governs OUTBOUND connections as well as bind (measured): under --allow-net=0.0.0.0:3000, a fetch to any other address fails with NotCapable the same way a bind does, so a scoped grant refuses every database, broker and outbound API call the project makes. If you scope it anyway, you get a second, independent guarantee on top of the build-level isolation above: a bind on 127.0.0.1:4919 fails under the start grant with NotCapable: Requires net access to "127.0.0.1:4919", so even a connector that reached production by mistake cannot open its port. The loopback restriction itself is the listener's, not a permission flag's — the runtime-owned listener binds 127.0.0.1 before anything else and refuses a non-loopback bind outright.

Protocol

Six signed GET operations — /v1/status, /v1/snapshot, /v1/events?after=<N>&limit=<N>, and the inspector operations /v1/health (M98d), /v1/config (M98e) and /v1/queues?after=<N>&limit=<N> (M98f) — over bounded polling. The status body carries an inspectors manifest (health, configuration and queues implemented; the rest reserved and false until their own operations ship); a client paired against a legacy three-field status body resolves it to all-false, and its health(), configuration(), queues() and scheduler() answer a typed unsupported without sending the request. Requests authenticate with X-Setu-Session, X-Setu-Sequence (strictly monotonic), X-Setu-Instance, and X-Setu-Mac (HMAC-SHA-256 over canonical newline-joined fields, verified via subtle.verify). Responses are signed over their exact bytes; the client verifies BEFORE parsing anything. Bodies are bounded (256 KiB), events are capped at 128 per read, and a fixed set of value-free error codes (invalid-request, unauthorized, expired, unsupported-version, unavailable, rate-limited) never reflects input. See docs/diagnostics-protocol.md in the repository for the complete wire specification and fixtures.

Bounds: at most 8 simultaneous handlers with one slot reserved against unpaired floods, an anonymous refusal budget of 5 requests/second (burst 10), a per-session budget of 20 requests/second (burst 40), and an 8 KiB header budget. Expiry uses the runtime's monotonic clock.

Native client

createDiagnosticsClient is the reviewed client-side implementation, consumed by the separately maintained devtool. Every dependency is injected (subtle, fetch, a timing port); calls are serialized with strictly increasing sequence numbers; the initial pairing exchange is terminal on failure; response MACs verify over the exact bounded bytes before parsing.

client.session() returns the authenticated remaining lifetime. When its renewal member is not null, client.renew() extends the same session — same key, session ID, instance binding and sequence space — by at most one ttlMs window and never beyond the activation-time maxSessionLifetimeMs. Schedule renewal with margin, normally after half of expiresInMs. Omitting maxSessionLifetimeMs preserves the legacy status bytes and expiry timer and makes renew() throw locally without probing /v1/renew.

The M98d inspector operation is read through client.health(): Promise<HealthDiagnosticsSnapshot> — the minimized health-observation snapshot the health plugin registers under CAPABILITIES.HEALTH_DIAGNOSTICS. A connector without a health source answers a typed unsupported; the client surfaces the snapshot's state rather than failing the call.

The M98e inspector operation is read through client.configuration(): Promise<ConfigDiagnosticsSnapshot> — the value-free provenance snapshot the config plugin registers under CAPABILITIES.CONFIG_DIAGNOSTICS (always registered, so "no config plugin" answers unsupported where "present but off" answers disabled). Every string from the config plugin is an application-approved display alias, and the connector and client both refuse an alias carrying a control character, whoever registered the source: no configuration value, hash, length, raw key name, or file path is ever carried, and unapproved keys are never observed at all.

The M98f queue inspector is read through client.queues(after, limit?): Promise<QueueDiagnosticsBatch>. The cursor is the CONNECTOR's merge cursor: every QueuePlugin instance contributes its own queue-diagnostics source, and each queue read drains every source's new attempts into one bounded merge ring before serving the page. The batch carries one status per source (a q<N> id, the approved instance alias, a per-source lost for attempts that source's own ring evicted before the connector drained them), the page of attempts, and every source's latest depths. With no queue plugin registered the connector answers state: 'unsupported'.

The M98l realtime inspector is read through client.realtime(): Promise<RealtimeDiagnosticsResponse>. Each WebSocket, SSE and realtime-backplane plugin contributes one source with a fixed sourceKind; websocket and sse sources carry current openConnections/groups gauges read from the plugin's own service, a backplane reports its gauges as unsupported, and a source that cannot be read appears as a value-free snapshot of kind unknown. With no realtime plugin registered the connector answers state: 'unsupported'.

The M98n outbound HTTP inspector is read through client.outboundHttp(): Promise<OutboundHttpDiagnosticsResponse>. Each createObservedFetch helper from @setu-ts/sdk whose plugin the application registered contributes one source counting the attempts made through that helper's fetch — never a URL, header, body or error. With no helper registered the connector answers state: 'unsupported'. The M98m storage inspector is read through client.storage(): Promise<StorageDiagnosticsResponse>, the same aggregate shape as the M98i cache inspector. Each StoragePlugin instance contributes one source; a source that cannot be read appears as a value-free collection-failed snapshot. With no storage plugin registered the connector answers state: 'unsupported'.

The full public surface is documented in PUBLIC_API.md.

Privacy

The connector serves M98a's minimized projections only: allowlisted labels, opaque ids, bounded counts, value-free failure codes. No request bodies, headers, credentials, payloads, logs, or environment values ever cross the protocol. Diagnostic counters are in-process and value-free.

The M98d health inspector carries the same discipline: each observation holds only the approved display alias, the framework's own status, the outcome state, and monotonic timing. An indicator's data, the thrown value of a failure, and any absolute time are never projected — the canary test plants both and asserts their absence at the source, in the raw signed bytes captured below the client, and in the client DTO. The connector validates the projected DTO before signing it; a source that violates it answers collection-failed.

The M98e configuration inspector holds it too: canary values planted in an unapproved key, inside the approved file, and inside an expanded reference's resolution are asserted absent at all three layers, as are the raw key names and the configured path. droppedEntries counts only budget omissions — a count of unapproved keys would disclose that they exist, so there is none.

The M98i cache inspector (GET /v1/cache, client.cache()) serves every CachePlugin instance's operation counters — per fixed operation, under each instance's approved alias — from at most 16 multi-provider sources resolved at bootstrap (more refuses startup). Keys, prefixes, values, URLs, factory results and errors never reach any layer; the e2e canary plants each and asserts its absence in the source snapshot, the raw signed bytes and the client DTO.

The M98k scheduler inspector (GET /v1/scheduler, client.scheduler()) serves every SchedulerPlugin instance's execution observations — contended, lock-failed and dispatched fires with wall-clock lateness, and handler attempts with their retry count — from at most 16 multi-provider sources resolved at bootstrap. Job names, cron expressions, payloads, job ids, lock keys and thrown errors never reach any layer; the e2e canary plants each and asserts its absence in the source snapshot, the raw signed bytes and the client DTO, and proves a lock loser produces no handler record. A skipped local fire is never reported as a globally missed execution. The M98m storage inspector (GET /v1/storage, client.storage()) serves every StoragePlugin instance's operation counters — per fixed operation, under each instance's approved alias — from at most 16 multi-provider sources resolved at bootstrap (more refuses startup), the M98i cache rule. Object paths, stored bytes, content types, signed URLs and error text never reach any layer; the e2e canary plants each and asserts its absence in the source snapshot, the raw signed bytes and the client DTO.

The M98g trace inspector (GET /v1/traces?after=N&limit=N, client.traces(after, limit?)) serves the TelemetryPlugin's completed, sampled spans under the same rules: only approved operation aliases, W3C-validated identifiers, at most eight link identifier pairs, kind, outcome, duration and monotonic age. Span names, attributes, events, resource labels, tracestate, baggage, exceptions and status messages never reach any layer — the e2e canary plants a hostile span name and a hostile attribute and asserts their absence in the batch, the raw signed bytes and the client DTO. Correlation joins EQUAL trace ids across independently authenticated sessions; an identifier grants no discovery or connection authority, parentVisibility never fabricates an edge, and ageMs is arrival age at one process, never a global timeline.

Exports

| Export | Kind | | ---------------------------- | --------- | | createDiagnosticsClient | function | | DiagnosticsPlugin | function | | DiagnosticsClientOptions | interface | | DiagnosticsPluginOptions | interface | | DiagnosticsSessionLifetime | interface | | IDiagnosticsClient | interface | | IDiagnosticsPlugin | interface |

Generated from the package barrel by pnpm run docs:exports; pnpm run check:docs fails when it drifts.