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

@txp-labs/sensitive-data-spec

v0.6.0

Published

The sensitive-data spec (classes, normalization, prompt carryover) and a zero-dependency classifier for in-memory redaction of conversation turns.

Readme

@txp-labs/sensitive-data-spec

The sensitive-data spec (version 0.7) and a classifier for conversation turns, for in-memory redaction in a call engine. It has no runtime dependencies. It never logs, stores or returns a detected value: results are classes and offsets.

On npm: npm install @txp-labs/sensitive-data-spec. From 0.5.0 every release publishes it from this repository's release workflow with npm provenance; npm audit signatures verifies it.

Between releases, depend on it by git commit. The compiled dist/ is committed (package managers do not build git dependencies), so pin a commit on main, for example with pnpm:

"@txp-labs/sensitive-data-spec": "github:txp-labs/sensitive-data-scanner#<commit>&path:packages/spec-ts"

Use

import { armedClasses, classify, loadSpec, redactTurns } from '@txp-labs/sensitive-data-spec';

const spec = loadSpec();
const turns = [
  { speaker: 'bot', text: 'Please enter or say your nine digit Social Security number.' },
  { speaker: 'customer', channel: 'dtmf', text: '123456789#' },
] as const;

classify(spec, [...turns]).matches;
// [{ class: 'us_ssn', via: 'prompt', confidence: 'high', turn: 1, start: 0, end: 9,
//    origStart: 0, origEnd: 9, parts: [...] , ... }]

redactTurns(spec, [...turns]);
// ['Please enter or say your nine digit Social Security number.', '#########']

// Before the answer arrives: what the next customer entry will be.
armedClasses(spec, [turns[0]]); // ['us_ssn', 'us_itin']
  • classify(spec, turns, { now }) returns every match in the conversation:

    • class, via (prompt / context / shape) and confidence (high / medium / low);
    • the span in the normalized text (turn, start, endTurn, end);
    • the span in the original text (origStart, origEnd);
    • parts, one per turn, for a value split across turns.

    It also returns the values set aside as published test data (excluded), and a count of numbers dropped because a word like "order" or "phone" was next to them (suppressed).

  • redactTurns masks every part of every match in the original texts.

  • armedClasses gives the classes the last prompt armed for the next customer turn (promptCarryover.turns: 1; a retry re-arms). An SSN prompt arms us_ssn and us_itin.

  • isMenuOrQuestion tells whether a bot or agent turn is a menu or a question, which ends a value the caller is still giving.

  • normalize(text, spec.normalize) and toOriginal expose the normalization and its offset map.

  • promptRegex(phrase) wraps a phrase in the spec's prompt boundary (neither a letter nor a digit on either side; case-insensitive, global). Use it for a phrase of your own instead of copying the boundary.

Offsets are UTF-16 code units, the same as JavaScript string indexes.

Versions: the package and the spec

These are two separate numbers:

  • The package version (version in package.json) follows the repository's releases. It is the same as the scanner's version and changes only when a release is cut (docs/RELEASING.md). Between releases, a commit on main keeps the last release's version even when the spec under it has moved on. So the package said 0.2.0 at the spec 0.3 commit, and it says 0.6.0 from release 0.6.0 on (0.3.0 was prepared and never published).
  • The spec version (SPEC_VERSION, and specVersion in the spec files and in loadSpec().specVersion) follows the spec (spec/README.md, Stability). It changes whenever the contract does, in whatever commit changes it.

When you pin a commit, check SPEC_VERSION to know which contract you have. Do not rely on the package version for that.

Tested against the contract

npm test runs every case in vectors/. The Python runner's test suite runs this package too (scripts/parity.ts) and fails if the two disagree on any vector.

The spec is compiled into src/spec.generated.ts from spec/*.yaml by npm run gen:spec. CI fails if the compiled copy is out of date.

dist/ is committed and built by npm run build. CI rebuilds it and fails if the result differs from what is committed, so after any change under src/ run npm run build and commit dist/ with it.