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

@qadi/audit

v0.8.0

Published

GxP-style audit trail, staging, circuit breaker, retention, and e-signature capture for @qadi/core, composed onto DecisionSink

Readme

@qadi/audit

Audit trail, staging, a circuit breaker, retention/archival, and e-signature capture for @qadi/core, composed into one assembled pipeline hung off DecisionSink.

pnpm add @qadi/audit @qadi/core effect

Narrows ADR-QD-016 the way ADR-QD-054 narrowed ADR-QD-024: an optional, separately versioned, dependency-free companion package — @qadi/core gains no dependency of any kind through this package existing, and @qadi/audit itself opens no connection, generates no key, and assumes no schema. Every capability that needs real storage, identity or crypto is a caller-supplied port.

import { AuditDecisionSinkLive } from "@qadi/audit";
import * as Layer from "effect/Layer";

const AppLayer = AuditDecisionSinkLive({ failureThreshold: 5, resetTimeoutMs: 30_000 }).pipe(
  Layer.provide(myAuditTrailPortLive), // the caller's own storage
);

Assembled, not individually correct

This is the whole point of the package: AuditDecisionSinkLive's record() sequence — encode, stage if wired, write, react to the outcome — is reachable through the one call every evaluation already makes, unlike the reference implementation this was compared against, where the equivalent pieces were each unit-tested and never called from the real enforcement path.

Refuses rather than approximates

A resource carrying a value with no safe durable representation fails AuditEntryNotEncodable rather than being partially written or silently dropped. An unknown decommissioning step id fails UnknownDecommissioningStep rather than silently no-opping. No e-signature default ships, not even a no-op one — Qadi.enforce's existing fail-closed behavior on an unwired obligation is the safe default already.

Not tamper-evident (WD-07)

The audit trail this package produces is not cryptographically tamper-evident, and archiving it does not make it so. verifySequenceIntegrity (see SequenceIntegrity.ts) catches a gap or a duplicate in a caller-assigned sequence number — accidental loss or reordering in the caller's own store — not deliberate tampering: there is no per-entry hash, nothing links one entry to the next, and an attacker who can modify stored rows can renumber them and pass the check. AuditArchive's keyMaterial is opaque pass-through metadata this package never uses to sign or verify anything (see AuditArchive.ts), and DecommissioningChecklist's "Revoke signing keys" step names an action this package has no part in performing. If a deployment needs tamper-evidence — a hash chain, a signature per archive, a WORM store — that has to be built and verified outside this library; nothing here provides it or claims to.

Structurally outside the pipeline

Retention, archival, sequence-integrity verification (gap-and-duplicate detection — not cryptographic tamper-evidence, see SequenceIntegrity.ts) and the decommissioning checklist are pure functions and data — caller-invoked, caller-scheduled, since this package has no scheduler of its own. E-signature capture is wired through Qadi.ts's ObligationHandler, not DecisionSink:

Nothing here connects the two: getPurgeableEntries selects by age alone and has no idea whether an entry was ever handed to archiveAuditTrail. Archive before you purge is a documented invariant a caller must uphold itself, not one this package can check — see the doc comments on Retention.ts's exports.

import { signatureObligationHandler, SIGNATURE_MEANINGS } from "@qadi/audit";
import * as Qadi from "@qadi/core";

Qadi.enforce(policy, {
  onObligations: signatureObligationHandler(mySignaturePort, SIGNATURE_MEANINGS.APPROVED),
});

Testing

AuditTrailPortTest/AuditStagingPortTest ship as public, deterministic, in-memory Layer factories for any consumer's own tests.

See ADR-QD-056.

License

MIT