Redactive is a high-performance TypeScript redaction library. It supports immutable cloning, explicit mutation, structured path rules, wildcards, content detectors, inspection, safety limits, and opt-in generated exact-path mutation.
- Runtime: Node.js 22 or newer
- Package manager: pnpm 11.11.0
- Module format: ESM
- Language: strict TypeScript
- Test runner: Vitest
- Benchmark runner: Mitata
Use pnpm for all repository commands. Do not introduce npm or yarn lockfiles.
Preserve these contracts unless the requested change explicitly updates the public API:
- Clone mode is the default and must not mutate the input.
- Mutation is explicit through
mode: 'mutate'or the mutation method. - Code generation is opt-in through
codegen: true. It must never become an implicit fallback. - Unsupported codegen configurations must throw
RedactiveCodegenUnsupportedError. - Codegen accepts only trusted, application-owned configuration and uses
new Function. - Safe and generated exact plans must preserve the same observable redaction semantics.
- Structured traversal must not invoke getters or inherited properties.
- Property access must use own data descriptors and preserve documented property behavior.
- Circular references, shared references, arrays, built-in containers, limits, and prototypes must retain their documented handling.
- Inspection records must never expose original sensitive values, previews, captures, or hashes.
- Core and browser-compatible exports must not acquire Node-only runtime dependencies.
Security or semantics changes require targeted regression tests. Prefer explicit failure over a silent reduction in protection.
- Keep TypeScript strict and avoid
any, non-null assertions, and unchecked casts. - Use type-only imports where appropriate.
- Use
.jsextensions in relative TypeScript imports because emitted files are ESM. - Add JSDoc comments to types, interfaces, public members, and functions for inline documentation.
- Document security-sensitive behavior, trusted-input assumptions, and thrown errors.
- Keep public types available through the intended package export.
- Do not edit or commit
dist; it is generated bypnpm build.
src/create-redactor.ts: public redactor construction and plan dispatch.src/types.ts: public configuration and result types.src/compiler/: option validation, path parsing, safe plans, wildcard plans, and codegen.src/traversal/: complete iterative structured traversal and text scanning.src/detectors/,src/replacements/, andsrc/presets/: built-in policy components.src/http/: Web-standard HTTP helpers.src/node/: explicitly Node-only helpers.test/security/,test/property/, andtest/adversarial/: high-value invariant coverage.
Choose the narrowest execution plan that fully preserves configured semantics. Keep the complete iterative engine as the compatibility path for complex policies.
Add or update tests for every behavioral change. Use unit tests for focused behavior, property tests for safe/codegen parity, security tests for unsafe inputs, and adversarial tests for termination and limits.
The codegen example intentionally imports from redactive like a package consumer. Vitest maps only
that exact package name to src/index.ts, allowing pnpm test to work on a clean checkout without
dist. Do not remove this alias merely to fix package resolution. Built-package behavior is checked
separately by public type, runtime, and package validation.
Useful commands:
pnpm test
pnpm typecheck
pnpm lint
pnpm test:types
pnpm test:runtime
pnpm validateRun pnpm validate before handing off a completed change. It covers formatting, linting, type
checking, tests, public types, runtime compatibility, build output, package metadata, unused code,
and benchmark smoke checks. Also run git diff --check.
When changing test or module resolution, verify from a clean generated state:
node scripts/clean.mjs
pnpm test
pnpm validate- Use Mitata. Do not replace it with Tinybench.
- Keep benchmark fixture construction outside timed operations.
- Verify every competitor and output contract before timing.
- Run performance benchmarks sequentially to avoid CPU contention.
- Default runs retain Mitata's
do_not_optimizebarrier. --optimizeddisables that barrier to observe V8-optimized hot code.- Group A and Group C use
fast-redactwithserialize: falseand include restoration. - Group F separately compares
fast-redact's default JSON serialization and internal restoration. - Redactive mutation serialization cases use fixture-specific reset and are not a general restore API. Redactive clone cases are the general source-preserving comparison.
- Do not describe narrower competitor workloads as feature-equivalent.
Commands:
pnpm benchmark
pnpm benchmark --optimized
pnpm benchmark -- --filter=exact
pnpm benchmark -- --filter=serializationUpdate benchmarks/RESULTS.md only from stable, repeated measurements. Record the runtime, operating
system, processor, and harness version, and treat isolated JIT outliers as noise.
- Keep examples runnable and covered by
test/integration/examples.test.ts. - Use consumer-style
from 'redactive'imports where the example demonstrates published usage. - Update README API documentation when public behavior changes.
- Add a changeset for user-visible changes and keep the changelog accurate.
- Preserve package export compatibility and validate it with
publint.
CI tests supported Node.js versions and caches the pnpm store using pnpm-lock.yaml. The publish
workflow uses npm trusted publishing with OIDC and runs on manual dispatch or a published GitHub
release. Do not add long-lived npm tokens or weaken release validation.
Preserve unrelated user changes in a dirty worktree. Inspect existing changes before editing overlapping files. Avoid destructive Git commands. Keep generated artifacts, coverage output, and temporary profiling data out of commits.