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

@pmcollab/coworkstream-audit

v0.1.0

Published

Append-only event log for @pmcollab/coworkstream. Captures every action and engine event for compliance, debugging, and agent training.

Readme

@pmcollab/coworkstream-audit

Tamper-evident, append-only event log for @pmcollab/coworkstream. Each entry is hash-chained to the previous via SHA-256 over a canonical serialization of the entry, so any post-hoc mutation is detectable provided the adapter satisfies the contract below.

Install

npm install @pmcollab/coworkstream-audit

Use

import { createAuditLog, createMemoryAdapter, createAuditAdapter } from '@pmcollab/coworkstream-audit'

const log = createAuditLog({ adapter: createMemoryAdapter() })
await log.append({ type: 'workstream.action_fired', itemId: 'i1', action: 'approve', userId: 'u1' })

const history = await log.read({ itemId: 'i1' })
const verification = await log.verify() // { ok: true } or { ok: false, brokenAt, reason }

// Periodically checkpoint the head outside this trust domain (recommended):
const head = await log.getHead()
await fetch('https://checkpoint.example.com/anchors', {
  method: 'POST',
  body: JSON.stringify({ logId: 'workstream', head, at: new Date().toISOString() }),
})

Wiring into the engine and HTTP API

Both @pmcollab/coworkstream-engine and @pmcollab/coworkstream-server accept an optional audit callback. Bridge them in:

const engine = createEngine({
  ...,
  store: { ...myStore, audit: createAuditAdapter(log) },
})

Now every dispatch, escalation, auto-resolve, and human resolution is captured.

Adapter contract — REQUIRED behaviors

Adapters that violate this contract will produce a chain that cannot be verified. This is a security contract, not a soft expectation.

interface AuditAdapter {
  /** Persist an entry exactly as written. Field set MUST be preserved. */
  append(entry: AuditEntry): Promise<void>

  /**
   * Return entries IN APPEND ORDER (oldest first), unless `reverse: true`.
   * Adapters that cannot guarantee order must store and return a monotonic
   * `seq` field and order by it.
   */
  readAll(filter?: AuditFilter): Promise<AuditEntry[]>

  /** Optional. */
  count?(): Promise<number>
}

Concretely:

  1. Insertion-order preservation. verify() walks readAll({}) linearly and validates entry[i].prevHash === entry[i-1].hash. If your storage is a SQL table without a seq column, add one and ORDER BY seq in readAll.
  2. Field-set preservation. The canonical hash includes every field on the entry. An adapter that drops undefined fields is fine (the hasher already does that), but one that adds extra fields at read time will break verification.
  3. Append-only at the storage layer. The chain detects post-hoc mutation, but only if the adapter does not silently overwrite entries. For Postgres, grant only INSERT to the writer role and lock the audit table against UPDATE/DELETE via a trigger. For object stores (S3 + JSONL), use bucket policies that deny PutObject overwrites.
  4. Single-process append serialization is provided by this package; multi-process serialization is your responsibility. The recommended pattern for Postgres is:
    BEGIN;
    SELECT hash FROM workstream_audit ORDER BY id DESC LIMIT 1 FOR UPDATE;
    INSERT INTO workstream_audit (...) VALUES (...);
    COMMIT;

Threat model — what the chain detects, and what it doesn't

Detects:

  • Post-hoc mutation of any field on a stored entry (changes the hash; verify() fails at that entry).
  • Reordering of entries (changes which entry's prevHash matches which hash).
  • Insertion of a fabricated entry between two real ones, if the attacker cannot rewrite all subsequent entries.

Does NOT detect:

  • An attacker who has BOTH write access to the storage backend AND the ability to call append(). Such an attacker can rebuild the entire chain from any point and the result will verify cleanly.
  • Truncation of the tail (the chain stays internally consistent if the most-recent N entries are deleted).

Recommended mitigation for higher-assurance environments:

Periodically read log.getHead() and store the head hash in a separate trust domain (an HSM/KMS-signed checkpoint, a customer's S3 bucket with versioning, a third-party WORM log). At audit time, re-fetch the head and compare to the latest checkpoint. This converts the chain from "tamper-evident against the application" to "tamper-evident against everyone except parties with access to BOTH the application AND the checkpoint store."

License

Commercial. See LICENSE in the repository root.