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

@kitsy/cnos-var-server

v1.18.0

Published

Embeddable CNOS var (var.*) control-plane server: revisions, generations, atomic activation, audit log, and pluggable stores.

Readme

@kitsy/cnos-var-server

Embeddable CNOS var (var.*) control-plane server: immutable revisions, monotonic generations, atomic activation, optimistic concurrency, rollback, an append-only audit log, and pluggable storage. Library-first — never a sidecar. Standalone cnos var serve is a thin wrapper over the same library.

Roles

  • Embedded authority. Mount the handler on your existing Node server:
    import { fileStore, varServer } from '@kitsy/cnos-var-server';
    const store = fileStore('./.cnos/var-log.jsonl');
    // http.createServer:
    http.createServer(varServer(store, { documents })).listen(8080);
    // or express-style (no express dependency here):
    app.use('/cnos/vars', varServer(store, { base: '/cnos/vars', documents }));
  • Standalone central plane. serveVarServer(store, { port }) (backs cnos var serve).

Stores

| Store | Persistence | Use | |-------|-------------|-----| | memoryStore() | ephemeral, empty on restart | embedded/latched authorities; overlay degrades cleanly to static/default | | fileStore(path) | append-only JSONL log book | durable head + full audit; restart recovery; replay/time-travel |

Custom stores implement both append(event) and appendSubtreeDeactivation(event). The subtree operation must persist and fold the parent plus every listed descendant atomically; treating it as a parent-only append violates hierarchical deactivation.

Reads (store.head / status / revision) are synchronous and lock-free: they observe a single immutable per-scope state snapshot, so a concurrent append is never partially visible. append persists first, then swaps the snapshot in one synchronous assignment.

HTTP route table

Base defaults to /cnos/vars. Mutations live under {base}/admin/*.

| Method | Path | Body / Query | Success | Errors | |--------|------|--------------|---------|--------| | GET | {base}?key=<scope> or ?group=<scope> | — | 200 { generation, revision, schemaId?, effectiveAt, values } + ETag: <revision>; 304 when If-None-Match equals the current revision | 404 no-head when no active head; 400 bad-request | | POST | {base}/admin/revisions | { scope, document, schemaId?, schemaVersion?, actor?, reason?, idempotencyKey? } | 201 { scope, revision, generation, created } (200 when the content-addressed revision already existed) | 422 revision-invalid { issues } | | POST | {base}/admin/validate | { document, schemaId?, scope? } | 200 { valid, issues } | — | | POST | {base}/admin/activate | { scope, revision, expectedGeneration, actor?, reason?, idempotencyKey? } | 200 { scope, generation, revision, effectiveAt } | 409 revision-conflict { expectedGeneration, currentGeneration }; 404 not-found (unknown revision) | | POST | {base}/admin/deactivate | { scope, expectedGeneration, actor?, reason?, idempotencyKey? } | 200 { scope, generation, active: false } | 409 revision-conflict | | POST | {base}/admin/rollback | { scope, expectedGeneration, toRevision? \| toGeneration?, actor?, reason? } | 200 { scope, generation, revision, effectiveAt } | 409 revision-conflict; 404 not-found | | GET | {base}/admin/status?scope=<scope> | — | 200 { scope, active, generation, revision?, source, lastRejected? } | 400 bad-request | | GET | {base}/admin/history?scope=<scope> | — | 200 { scope, events: VarEvent[] } | 400 bad-request | | GET | {base}/admin/replay?scope=<scope>&toGeneration=<n> | — | 200 <ScopeHead> (persistent stores only) | 404 not-found; 400 store-unsupported (ephemeral store) |

Values keying (canonical). In every read response values is ALWAYS a JSON object keyed by the full var key minus var.. Scope kind is decided syntactically: a group is a single segment with no dot (agentic); a key contains a dot (agentic.lanes.vinci).

  • Key-scoped read wraps the as-authored document: values = { "<scope>": doc }.
  • Group-scoped read passes the document through; a group revision must be an object whose every top-level key starts with "<group>." — enforced at revisions/validate time (issue code var.group-scope-shape), so a malformed group document is rejected before it can activate.

ETag / 304. The ETag value is the content-addressed revision (sha256:...). A consumer sends If-None-Match: <revision>; an unchanged head returns 304 with no body.

Authorization. Every request runs through options.authorize({ kind, scope, token }). kind is 'read' (GET {base} — the data plane), 'audit' (GET {base}/admin/* — the append-only log, including actors, reasons and past document bodies) or 'mutate' (POST {base}/admin/*). audit is deliberately distinct from read so an authorizer can guard the audit trail without also closing the data plane.

scope is populated for all three kinds: from the key/group/scope query parameter for reads/audits, and from the request body's scope field for mutations — the body is parsed BEFORE the hook runs so scoped (business/environment/component) authorization applies to writes too. token is parsed from Authorization: Bearer …. Default is allow-all with a one-time stderr warning; staticBearerAuthorize(tokens) is provided for dev/CI (it does not distinguish the three kinds). Denied → 403.

Request limits. Bodies are read before authorization, so they are bounded: over options.maxBodyBytes (default 1 MiB) a request is rejected 413 payload-too-large. A malformed request — missing/wrongly typed body field, unparseable JSON — is 400 bad-request (store-unsupported now means only what it says: the active store cannot serve an otherwise well-formed operation).

Commit seam (engine.onCommit)

VarEngine.onCommit(listener) fires after every accepted activation/deactivation (rollback flows through activate, so it is covered), receiving { scope, kind, head } with the store already updated. It returns an unsubscribe function. This is the reusable push seam behind the rpc Subscribe stream in @kitsy/cnos-var-rpc (attachVarRpc / serveVarRpc); ws/sse will reuse it unchanged.

A deactivated commit pushes a no_head SnapshotBatch carrying the affected scope. That message is not decorative: consumer SDKs turn it into an atomic removal of the scope's runtime tier so reads fall back to value.* / schema defaults. Since a subscribe-capable source is never polled, dropping it would leave a consumer serving a deactivated revision indefinitely.

To make http-admin mutations reach rpc subscribers, both planes must share ONE engine:

const engine = createVarEngine(store, { documents });
http.createServer(varServer(store, { engine, documents })).listen(8790);
attachVarRpc(grpcServer, store, { engine, documents });   // same engine

cnos var serve --port 8790 --rpc 8791 does exactly this.

Event-log format (fileStore)

One JSON object per line (JSONL), appended forever. Event kinds: revision-created, activated, deactivated, rejected.

{ "kind": "revision-created", "scope": "agentic.lanes.vinci", "revision": "sha256:…",
  "document": { "enabled": true, "model_target_ref": "secret.ops.model" },
  "schemaId": "agentic-lanes/v1", "actor": "ops", "timestamp": "2026-07-20T…Z" }
{ "kind": "activated", "scope": "agentic.lanes.vinci", "revision": "sha256:…",
  "generation": 1, "previousGeneration": 0, "actor": "ops", "reason": "enable vinci",
  "timestamp": "2026-07-20T…Z" }
{ "kind": "rejected", "scope": "agentic.lanes.vinci",
  "rejectionReason": "document.unknown-field: Unknown field 'budgets2' …",
  "timestamp": "2026-07-20T…Z" }
  • Current head = fold of the log (last activation not followed by a deactivation).
  • Generations are monotonic per scope; every activated/deactivated allocates the next one. Rollback re-activates a prior revision as a new generation — the log is never rewritten.
  • Restart recovery: the store replays the log on construction and resumes from the last activation — never from fallback.
  • No secret material: documents carry var.* values and opaque secret.* ref strings only. Nothing in the log is ever a resolved secret.

Idempotency

Mutations accept a client idempotencyKey. A replayed request returns the original result without appending a second event. The map is rebuilt from the log on restart, so it survives across process boundaries for persistent stores.