field-redactor 1.1.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/.github/workflows/ci.yml +38 -0
  2. package/CHANGELOG.md +156 -0
  3. package/README.md +64 -647
  4. package/dist/configValidator.d.ts +10 -0
  5. package/dist/configValidator.d.ts.map +1 -0
  6. package/dist/configValidator.js +94 -0
  7. package/dist/configValidator.js.map +1 -0
  8. package/dist/copyOnWriteHelpers.d.ts +20 -0
  9. package/dist/copyOnWriteHelpers.d.ts.map +1 -0
  10. package/dist/copyOnWriteHelpers.js +58 -0
  11. package/dist/copyOnWriteHelpers.js.map +1 -0
  12. package/dist/customObjectManager.d.ts +13 -7
  13. package/dist/customObjectManager.d.ts.map +1 -1
  14. package/dist/customObjectManager.js +30 -29
  15. package/dist/customObjectManager.js.map +1 -1
  16. package/dist/dryRun.d.ts +8 -0
  17. package/dist/dryRun.d.ts.map +1 -0
  18. package/dist/dryRun.js +75 -0
  19. package/dist/dryRun.js.map +1 -0
  20. package/dist/dryRunAttribution.d.ts +8 -0
  21. package/dist/dryRunAttribution.d.ts.map +1 -0
  22. package/dist/dryRunAttribution.js +106 -0
  23. package/dist/dryRunAttribution.js.map +1 -0
  24. package/dist/fieldRedactor.d.ts +43 -5
  25. package/dist/fieldRedactor.d.ts.map +1 -1
  26. package/dist/fieldRedactor.js +124 -23
  27. package/dist/fieldRedactor.js.map +1 -1
  28. package/dist/fieldRedactorConfigBuilder.d.ts +49 -0
  29. package/dist/fieldRedactorConfigBuilder.d.ts.map +1 -0
  30. package/dist/fieldRedactorConfigBuilder.js +98 -0
  31. package/dist/fieldRedactorConfigBuilder.js.map +1 -0
  32. package/dist/fieldRedactorDeps.d.ts +17 -0
  33. package/dist/fieldRedactorDeps.d.ts.map +1 -0
  34. package/dist/fieldRedactorDeps.js +41 -0
  35. package/dist/fieldRedactorDeps.js.map +1 -0
  36. package/dist/index.d.ts +7 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +14 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/jsonWalk.d.ts +11 -0
  41. package/dist/jsonWalk.d.ts.map +1 -0
  42. package/dist/jsonWalk.js +86 -0
  43. package/dist/jsonWalk.js.map +1 -0
  44. package/dist/objectRedactor.d.ts +9 -34
  45. package/dist/objectRedactor.d.ts.map +1 -1
  46. package/dist/objectRedactor.js +11 -271
  47. package/dist/objectRedactor.js.map +1 -1
  48. package/dist/objectRedactorCow.d.ts +35 -0
  49. package/dist/objectRedactorCow.d.ts.map +1 -0
  50. package/dist/objectRedactorCow.js +300 -0
  51. package/dist/objectRedactorCow.js.map +1 -0
  52. package/dist/objectRedactorCustomObject.d.ts +49 -0
  53. package/dist/objectRedactorCustomObject.d.ts.map +1 -0
  54. package/dist/objectRedactorCustomObject.js +138 -0
  55. package/dist/objectRedactorCustomObject.js.map +1 -0
  56. package/dist/objectRedactorHelpers.d.ts +9 -0
  57. package/dist/objectRedactorHelpers.d.ts.map +1 -0
  58. package/dist/objectRedactorHelpers.js +58 -0
  59. package/dist/objectRedactorHelpers.js.map +1 -0
  60. package/dist/objectRedactorMutation.d.ts +10 -0
  61. package/dist/objectRedactorMutation.d.ts.map +1 -0
  62. package/dist/objectRedactorMutation.js +89 -0
  63. package/dist/objectRedactorMutation.js.map +1 -0
  64. package/dist/objectRedactorSync.d.ts +2 -0
  65. package/dist/objectRedactorSync.d.ts.map +1 -0
  66. package/dist/objectRedactorSync.js +7 -0
  67. package/dist/objectRedactorSync.js.map +1 -0
  68. package/dist/objectRedactorTraversal.d.ts +57 -0
  69. package/dist/objectRedactorTraversal.d.ts.map +1 -0
  70. package/dist/objectRedactorTraversal.js +576 -0
  71. package/dist/objectRedactorTraversal.js.map +1 -0
  72. package/dist/presets.d.ts +22 -0
  73. package/dist/presets.d.ts.map +1 -0
  74. package/dist/presets.js +50 -0
  75. package/dist/presets.js.map +1 -0
  76. package/dist/primitiveRedactor.d.ts +13 -8
  77. package/dist/primitiveRedactor.d.ts.map +1 -1
  78. package/dist/primitiveRedactor.js +32 -27
  79. package/dist/primitiveRedactor.js.map +1 -1
  80. package/dist/redactionRules.d.ts +23 -0
  81. package/dist/redactionRules.d.ts.map +1 -0
  82. package/dist/redactionRules.js +76 -0
  83. package/dist/redactionRules.js.map +1 -0
  84. package/dist/regexUtils.d.ts +3 -0
  85. package/dist/regexUtils.d.ts.map +1 -0
  86. package/dist/regexUtils.js +8 -0
  87. package/dist/regexUtils.js.map +1 -0
  88. package/dist/secretManager.d.ts +18 -5
  89. package/dist/secretManager.d.ts.map +1 -1
  90. package/dist/secretManager.js +49 -11
  91. package/dist/secretManager.js.map +1 -1
  92. package/dist/types.d.ts +110 -7
  93. package/dist/types.d.ts.map +1 -1
  94. package/dist/types.js +13 -6
  95. package/dist/types.js.map +1 -1
  96. package/dist/valuePatternMatcher.d.ts +15 -0
  97. package/dist/valuePatternMatcher.d.ts.map +1 -0
  98. package/dist/valuePatternMatcher.js +30 -0
  99. package/dist/valuePatternMatcher.js.map +1 -0
  100. package/docs/guides/anti-patterns.md +107 -0
  101. package/docs/guides/metadata-redaction.md +112 -0
  102. package/docs/guides/migration-1.2-to-1.5.md +106 -0
  103. package/docs/guides/secret-key-modes.md +108 -0
  104. package/docs/guides/value-pattern-redaction.md +58 -0
  105. package/docs/reference/config.md +135 -0
  106. package/docs/release-notes/2.0.0.md +19 -0
  107. package/docs/release-notes/2.1.0.md +17 -0
  108. package/docs/release-notes/2.2.0.md +16 -0
  109. package/docs/release-notes/2.3.0.md +17 -0
  110. package/docs/release-notes/2.3.1.md +17 -0
  111. package/docs/release-notes/2.4.0.md +30 -0
  112. package/docs/release-notes/2.5.0.md +33 -0
  113. package/docs/release-notes/2.5.1.md +17 -0
  114. package/docs/release-notes/README.md +30 -0
  115. package/docs/release-notes/v1.0.0.md +17 -0
  116. package/docs/release-notes/v1.1.0.md +18 -0
  117. package/docs/release-notes/v1.2.0.md +18 -0
  118. package/docs/release-notes/v1.2.1.md +16 -0
  119. package/docs/release-notes/v1.2.2.md +19 -0
  120. package/docs/release-notes/v1.3.0.md +112 -0
  121. package/docs/release-notes/v1.5.0.md +88 -0
  122. package/jest.config.js +4 -1
  123. package/package.json +3 -3
@@ -0,0 +1,135 @@
1
+ # Configuration reference
2
+
3
+ ## Overview
4
+
5
+ | Doc label | Config field | Type | Default | Effect |
6
+ |-----------|--------------|------|---------|--------|
7
+ | — | `redactor` | `(val) => Promise<string>` | `"REDACTED"` async | Custom async redactor; enables async traversal when sole redactor |
8
+ | — | `syncRedactor` | `(val) => string` | `"REDACTED"` sync | Sync redactor; enables `redactSync()` without per-field Promises |
9
+ | **Shallow** | `secretKeys` | `RegExp[]` | `null` | Redact matching scalar values; if no rules at all, everything matches |
10
+ | **Deep** | `deepSecretKeys` | `RegExp[]` | `[]` | Deeply redact all primitives under matching keys |
11
+ | **Opaque** | `fullSecretKeys` | `RegExp[]` | `[]` | Stringify and redact entire values |
12
+ | **Remove** | `deleteSecretKeys` | `RegExp[]` | `[]` | Delete matching keys |
13
+ | **Schema** | `customObjects` | `CustomObject[]` | `[]` | Per-shape rules; see [metadata guide](../guides/metadata-redaction.md) |
14
+ | **Value-pattern** | `valuePatterns` | `RegExp[]` | `[]` | Opt-in: redact scalars whose string form matches a pattern |
15
+ | — | `schemaNames` | `string[]` | — | Optional labels parallel to `customObjects` for `dryRun` reports |
16
+ | — | `ignoreBooleans` | `boolean` | `false` | Skip boolean redaction when `true` |
17
+ | — | `ignoreNullOrUndefined` | `boolean` | `true` | Skip null/undefined redaction when `true` |
18
+ | — | `cloneInput` | `boolean` | `true` | Copy-on-write for `redact()` / `redactSync()` |
19
+ | — | `strict` | `boolean` | `false` | Throw on config warnings when `true` |
20
+ | — | `onConfigWarning` | `(msg) => void` | — | Callback for non-fatal config warnings |
21
+
22
+ ## FieldRedactor API
23
+
24
+ | Method | Returns | Notes |
25
+ |--------|---------|-------|
26
+ | `redact(value)` | `Promise<T>` | Copy-on-write by default |
27
+ | `redactSync(value)` | `T` | Sync path when no async-only `redactor` |
28
+ | `redactInPlace(value)` | `Promise<void>` | Mutates traversable input |
29
+ | `redactInPlaceSync(value)` | `void` | Sync in-place |
30
+ | `dryRun(value)` | `Promise<{ result, report }>` | Redact + path audit |
31
+ | `dryRunSync(value)` | `{ result, report }` | Sync dry run |
32
+ | `configWarnings` | `readonly string[]` | Warnings from construction |
33
+
34
+ ### Static factories
35
+
36
+ - `FieldRedactor.createSafe(config)` — requires at least one rule; throws `FieldRedactorConfigurationError` otherwise
37
+ - `new FieldRedactor(config)` — legacy; no rules ⇒ redact everything
38
+
39
+ ## Builder API
40
+
41
+ ```typescript
42
+ import { CustomObjectMatchType, FieldRedactorConfigBuilder } from 'field-redactor';
43
+
44
+ const redactor = FieldRedactorConfigBuilder.create()
45
+ .usePreset(presets.applicationLogging())
46
+ .valuePattern(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/)
47
+ .shallow(/ssn/i)
48
+ .deep(/accountInfo/i)
49
+ .opaque(/rawPayload/i)
50
+ .remove(/authKey/i)
51
+ .schema(metadataSchema, { name: 'metadata-entry' })
52
+ .syncRedactor((val) => `REDACTED:${val}`)
53
+ .strict()
54
+ .buildSafeRedactor();
55
+ ```
56
+
57
+ Methods: `shallow`, `deep`, `opaque`, `remove` / `delete`, `schema`, `valuePattern`, `usePreset`, `redactor`, `syncRedactor`, `ignoreBooleans`, `ignoreNullOrUndefined`, `cloneInput`, `strict`, `onConfigWarning`, `build`, `buildRedactor`, `buildSafeRedactor`.
58
+
59
+ ## Configuration validation
60
+
61
+ ```typescript
62
+ import { validateFieldRedactorConfig } from 'field-redactor';
63
+
64
+ const warnings = validateFieldRedactorConfig({ secretKeys: [/email/] });
65
+ ```
66
+
67
+ Warnings include: no rules configured, duplicate regex across key groups, global regex flag, missing schema sibling keys, overlapping schemas. Set `strict: true` to throw on warnings.
68
+
69
+ ## Presets
70
+
71
+ ```typescript
72
+ import { FieldRedactor, presets } from 'field-redactor';
73
+
74
+ FieldRedactor.createSafe({
75
+ ...presets.applicationLogging(),
76
+ secretKeys: [/ssn/] // extend defaults
77
+ });
78
+ ```
79
+
80
+ | Preset | Contents |
81
+ | --- | --- |
82
+ | `loggingMetadata()` | `{ name, type, value }` schema + auth key removal |
83
+ | `applicationLogging()` | Common PII patterns + event metadata schema |
84
+ | `keyValueEntries()` | `{ key, value }` schema |
85
+
86
+ ## Dry run report
87
+
88
+ ```typescript
89
+ type DryRunReport = {
90
+ redactedPaths: string[];
91
+ deletedPaths: string[];
92
+ matchedSchemas: { path: string; schemaIndex: number; schemaName?: string }[];
93
+ pathRules: {
94
+ path: string;
95
+ action: 'redact' | 'delete';
96
+ rule: 'schema' | 'opaque' | 'deep' | 'remove' | 'shallow' | 'value' | 'default';
97
+ pattern?: string;
98
+ schemaIndex?: number;
99
+ schemaName?: string;
100
+ }[];
101
+ };
102
+ ```
103
+
104
+ `pathRules` explains **why** each path changed (which rule matched). Use alongside `redactedPaths` / `deletedPaths` for iteration.
105
+
106
+ ## Errors
107
+
108
+ | Class | When |
109
+ | --- | --- |
110
+ | `FieldRedactorError` | Redaction failure at runtime |
111
+ | `FieldRedactorConfigurationError` | Invalid config, `createSafe()` with no rules, `strict` warnings |
112
+
113
+ ## `redactor` / `syncRedactor`
114
+
115
+ Provide `syncRedactor` (or use the default) when you want `redactSync()` without Promise overhead. Async-only `redactor` keeps `redact()` fully async.
116
+
117
+ ```typescript
118
+ import * as crypto from 'crypto';
119
+ import { FieldRedactor, Redactor } from 'field-redactor';
120
+
121
+ const redactor: Redactor = (val) =>
122
+ Promise.resolve(crypto.createHash('sha256').update(String(val)).digest('hex'));
123
+
124
+ const fieldRedactor = new FieldRedactor({ redactor, secretKeys: [/email/] });
125
+ ```
126
+
127
+ ## Object schemas (`customObjects`)
128
+
129
+ Highest precedence. See [Metadata redaction](../guides/metadata-redaction.md) for sibling-key patterns and [Secret key modes](../guides/secret-key-modes.md) for key-based modes.
130
+
131
+ ## Guides
132
+
133
+ - [Secret key modes](../guides/secret-key-modes.md)
134
+ - [Metadata redaction](../guides/metadata-redaction.md)
135
+ - [Anti-patterns](../guides/anti-patterns.md)
@@ -0,0 +1,19 @@
1
+ # Release notes — 2.0.0
2
+
3
+ > **Note:** `2.x` tags mark internal development milestones. The published npm line remains `1.x`; feature content through `2.0.0` is included in **v1.3.0**.
4
+
5
+ ## Added
6
+
7
+ - **`redactSync()`** and **`redactInPlaceSync()`** — synchronous redaction without per-field `Promise` overhead.
8
+ - **`syncRedactor`** config option for a dedicated synchronous redactor function.
9
+ - Shared sync traversal module extracted from the async path.
10
+
11
+ ## Migration
12
+
13
+ When using the default redactor, prefer `redactSync()` over `await redact()` on hot paths:
14
+
15
+ ```typescript
16
+ const output = redactor.redactSync(payload);
17
+ ```
18
+
19
+ Async `redact()` still works and delegates to the sync path when no async-only `redactor` is configured.
@@ -0,0 +1,17 @@
1
+ # Release notes — 2.1.0
2
+
3
+ > **Note:** `2.x` tags mark internal development milestones. The published npm line remains `1.x`; feature content through `2.1.0` is included in **v1.3.0**.
4
+
5
+ ## Added
6
+
7
+ - **Copy-on-write redaction** — `redact()` and `redactSync()` clone only mutated branches (`cloneInput: true` by default).
8
+ - **`cloneInput`** config option — set `false` to mutate the input in place (equivalent to `redactInPlace`).
9
+
10
+ ## Changed
11
+
12
+ - Replaced upfront full deep clone with structural sharing for default `redact()` / `redactSync()`.
13
+ - Unified in-place and copy-on-write traversal behind a shared `ContainerMutation` layer.
14
+
15
+ ## Behavior note
16
+
17
+ Unredacted subtrees may share references with the input. If you need every nested object to be a new reference, deep-clone before redacting.
@@ -0,0 +1,16 @@
1
+ # Release notes — 2.2.0
2
+
3
+ > **Note:** `2.x` tags mark internal development milestones. The published npm line remains `1.x`; feature content through `2.2.0` is included in **v1.3.0**.
4
+
5
+ ## Added
6
+
7
+ - **`FieldRedactor.createSafe()`** — requires at least one explicit redaction rule.
8
+ - **`dryRun()` / `dryRunSync()`** — returns `{ result, report }` with `redactedPaths`, `deletedPaths`, and `matchedSchemas`.
9
+ - **Configuration validation** — `validateFieldRedactorConfig()`, `configWarnings`, `strict`, `onConfigWarning`.
10
+ - **Presets** — `presets.loggingMetadata()`, `presets.applicationLogging()`, `presets.keyValueEntries()`.
11
+ - Onboarding docs: decision guide, cheat sheet, Shallow/Deep/Opaque/Remove/Schema labels.
12
+
13
+ ```typescript
14
+ const { result, report } = redactor.dryRunSync(sample);
15
+ console.log(report.redactedPaths);
16
+ ```
@@ -0,0 +1,17 @@
1
+ # Release notes — 2.3.0
2
+
3
+ > **Note:** `2.x` tags mark internal development milestones. The published npm line remains `1.x`; feature content through `2.3.0` is included in **v1.3.0**.
4
+
5
+ ## Added
6
+
7
+ - **`FieldRedactorConfigBuilder`** — fluent API mapping doc labels to config fields.
8
+ - **`schema(..., { name })`** — optional schema names in `dryRun` reports (`schemaName` on `matchedSchemas`).
9
+ - Split documentation: `docs/guides/` and `docs/reference/config.md`.
10
+
11
+ ```typescript
12
+ FieldRedactorConfigBuilder.create()
13
+ .shallow(/email/i)
14
+ .remove(/authKey/i)
15
+ .schema(metadataSchema, { name: 'metadata-entry' })
16
+ .buildSafeRedactor();
17
+ ```
@@ -0,0 +1,17 @@
1
+ # Release notes — 2.3.1
2
+
3
+ > **Note:** `2.3.1` is the final internal `2.x` milestone before the **v1.3.0** npm release. Package version at this tag is `2.3.1`; the equivalent published version is **v1.3.0**.
4
+
5
+ ## Added
6
+
7
+ - **`CHANGELOG.md`** — version history for the `1.x` npm line.
8
+ - **`prepublishOnly`** script — runs `yarn build` before npm publish.
9
+ - Release notes for all existing tags under `docs/release-notes/`.
10
+
11
+ ## Changed
12
+
13
+ - Package version at this tag set to `2.3.1` to match the git tag.
14
+
15
+ ## Published equivalent
16
+
17
+ For npm consumers, use **v1.3.0** (next commit on `master`). See [v1.3.0.md](v1.3.0.md).
@@ -0,0 +1,30 @@
1
+ # Release notes — 2.4.0
2
+
3
+ > **Superseded:** This internal milestone is included in npm **[v1.5.0](v1.5.0.md)**. Git tag `2.4.0` has been removed.
4
+
5
+ ## Added
6
+
7
+ - **`FieldRedactorConfigBuilder.usePreset()`** — merge a `presets.*()` return value (or any partial config) into the builder. Regex arrays and schemas accumulate; scalar options apply only when not already set.
8
+ - **`dryRun` rule attribution** — `report.pathRules` lists each redacted or deleted path with the matching rule (`schema`, `opaque`, `deep`, `remove`, `shallow`, or `default`), optional regex `pattern`, and schema metadata when applicable.
9
+ - **Exported types** — `DryRunPathRule`, `RedactionRuleLabel`, and `MatchedSchemaReport` from the public API.
10
+ - **Anti-patterns guide** — [docs/guides/anti-patterns.md](../guides/anti-patterns.md) documents common configuration mistakes (bare constructor, duplicate regexes, global flags, tuning without `dryRun`).
11
+
12
+ ```typescript
13
+ import { FieldRedactorConfigBuilder, presets } from 'field-redactor';
14
+
15
+ const redactor = FieldRedactorConfigBuilder.create()
16
+ .usePreset(presets.applicationLogging())
17
+ .shallow(/ssn/i)
18
+ .buildSafeRedactor();
19
+
20
+ const { report } = redactor.dryRunSync(payload);
21
+ // report.pathRules → [{ path: 'email', action: 'redact', rule: 'shallow', pattern: '/email/i' }, ...]
22
+ ```
23
+
24
+ ## Changed
25
+
26
+ - Package version at this tag set to `2.4.0` to match the git tag.
27
+
28
+ ## Published equivalent
29
+
30
+ Shipped in **[v1.5.0](v1.5.0.md)** on npm.
@@ -0,0 +1,33 @@
1
+ # Release notes — 2.5.0
2
+
3
+ > **Superseded:** This internal milestone is included in npm **[v1.5.0](v1.5.0.md)**. Git tag `2.5.0` has been removed.
4
+
5
+ ## Added
6
+
7
+ - **Value-pattern redaction** — opt-in `valuePatterns: RegExp[]` redacts scalar fields when their string form matches a pattern, regardless of key name. Lowest precedence: runs only when key-based rules leave the value unchanged.
8
+ - **`FieldRedactorConfigBuilder.valuePattern()`** — fluent builder method for `valuePatterns`.
9
+ - **`dryRun` value rule attribution** — `report.pathRules` includes `rule: 'value'` with the matching regex when value-pattern redaction fired.
10
+ - **Value-pattern guide** — [docs/guides/value-pattern-redaction.md](../guides/value-pattern-redaction.md).
11
+
12
+ ```typescript
13
+ import { FieldRedactor, FieldRedactorConfigBuilder } from 'field-redactor';
14
+
15
+ const emailPattern = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;
16
+
17
+ const redactor = FieldRedactor.createSafe({ valuePatterns: [emailPattern] });
18
+
19
+ const { report } = redactor.dryRunSync({
20
+ description: 'Contact alice@example.com',
21
+ note: 'no pii here'
22
+ });
23
+ // report.pathRules → [{ path: 'description', action: 'redact', rule: 'value', pattern: '...' }]
24
+ ```
25
+
26
+ ## Changed
27
+
28
+ - Package version at this tag set to `2.5.0` to match the git tag.
29
+ - Internal refactor: centralized field-redactor dependency wiring (`fieldRedactorDeps`), shared regex utilities, and simplified dry-run path attribution.
30
+
31
+ ## Published equivalent
32
+
33
+ Shipped in **[v1.5.0](v1.5.0.md)** on npm.
@@ -0,0 +1,17 @@
1
+ # Release notes — 2.5.1
2
+
3
+ > **Superseded:** This internal milestone is included in npm **[v1.5.0](v1.5.0.md)**. Git tag `2.5.1` has been removed.
4
+
5
+ ## Changed
6
+
7
+ - **Unified JSON traversal** — sync in-place, copy-on-write, and async in-place redaction now share `ObjectRedactorTraversal` with a common `ContainerMutation` adapter. `ObjectRedactor` is a thin orchestrator; `ObjectRedactorSyncTraversal` remains as a compatibility alias.
8
+ - **Shared custom-object handlers** — `objectRedactorCustomObject.ts` centralizes match-type `switch` logic used by both sync and async traversal paths.
9
+ - Package version at this tag set to `2.5.1` to match the git tag.
10
+
11
+ ## Fixed
12
+
13
+ - Async in-place redaction now uses the same `ContainerMutation` path as sync traversal, keeping nested object and array behavior consistent across redaction modes.
14
+
15
+ ## Published equivalent
16
+
17
+ Shipped in **[v1.5.0](v1.5.0.md)** on npm.
@@ -0,0 +1,30 @@
1
+ # Release notes index
2
+
3
+ Per-version release notes for published **field-redactor** git tags. npm releases use the same `v1.x.x` tag names.
4
+
5
+ | Version | npm | Notes |
6
+ | --- | --- | --- |
7
+ | **v1.5.0** | Yes | [v1.5.0.md](v1.5.0.md) — DX polish, value patterns, unified traversal |
8
+ | v1.3.0 | No (superseded by 1.5.0) | [v1.3.0.md](v1.3.0.md) — sync API, COW, builder, dryRun, presets |
9
+ | v1.2.2 | No | [v1.2.2.md](v1.2.2.md) |
10
+ | v1.2.1 | No | [v1.2.1.md](v1.2.1.md) |
11
+ | v1.2.0 | Yes | [v1.2.0.md](v1.2.0.md) |
12
+ | v1.1.0 | Yes | [v1.1.0.md](v1.1.0.md) |
13
+ | v1.0.0 | Yes | [v1.0.0.md](v1.0.0.md) |
14
+
15
+ ## Migration
16
+
17
+ - [1.2.x → 1.5.0](../guides/migration-1.2-to-1.5.md) — recommended upgrade path from the previous npm line.
18
+
19
+ ## Internal milestones (removed)
20
+
21
+ Git tags `2.0.0`–`2.5.1` tracked incremental development toward **v1.3.0** and **v1.5.0**. They were never published to npm and are removed from the repository. Their notes remain for archaeology:
22
+
23
+ | Tag | Notes |
24
+ | --- | --- |
25
+ | 2.4.0 | [2.4.0.md](2.4.0.md) — included in v1.5.0 |
26
+ | 2.5.0 | [2.5.0.md](2.5.0.md) — included in v1.5.0 |
27
+ | 2.5.1 | [2.5.1.md](2.5.1.md) — included in v1.5.0 |
28
+ | 2.0.0–2.3.1 | [2.0.0.md](2.0.0.md) … [2.3.1.md](2.3.1.md) — included in v1.3.0 / v1.5.0 |
29
+
30
+ Full history: [CHANGELOG.md](../../CHANGELOG.md).
@@ -0,0 +1,17 @@
1
+ # Release notes — v1.0.0
2
+
3
+ Initial public release of **field-redactor**.
4
+
5
+ ## Added
6
+
7
+ - `FieldRedactor` with async `redact()` and `redactInPlace()`
8
+ - Regex key rules: `secretKeys`, `deepSecretKeys`, `fullSecretKeys`
9
+ - **Schema** rules (`customObjects`) for shaped objects with sibling-key indirection
10
+ - Configurable `redactor` function (default replaces values with `"REDACTED"`)
11
+ - Deep-clone via `rfdc` so `redact()` leaves the input untouched
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ npm install field-redactor
17
+ ```
@@ -0,0 +1,18 @@
1
+ # Release notes — v1.1.0
2
+
3
+ ## Changed
4
+
5
+ - Root-level primitives, `null`, `undefined`, `Date`, and functions are returned unchanged instead of throwing `FieldRedactorError`.
6
+
7
+ This makes the redactor safe to call on values that may or may not be traversable JSON objects.
8
+
9
+ ```typescript
10
+ const redactor = new FieldRedactor({ secretKeys: [/email/] });
11
+
12
+ redactor.redact(undefined); // → undefined (no throw)
13
+ redactor.redact('plain string'); // → 'plain string'
14
+ ```
15
+
16
+ ## Full changelog
17
+
18
+ See [CHANGELOG.md](../../CHANGELOG.md#110---2025-01-30).
@@ -0,0 +1,18 @@
1
+ # Release notes — v1.2.0
2
+
3
+ ## Added
4
+
5
+ - **`deleteSecretKeys`** — Remove matching keys from the output entirely (**Remove** mode).
6
+
7
+ ```typescript
8
+ const redactor = new FieldRedactor({
9
+ deleteSecretKeys: [/authKey/i]
10
+ });
11
+
12
+ await redactor.redact({ username: 'alice', authKey: 'secret' });
13
+ // → { username: 'REDACTED' } (authKey key removed)
14
+ ```
15
+
16
+ ## Full changelog
17
+
18
+ See [CHANGELOG.md](../../CHANGELOG.md#120---2025-02-10).
@@ -0,0 +1,16 @@
1
+ # Release notes — v1.2.1
2
+
3
+ Bug-fix and ergonomics release for schema matching and sibling-key redaction.
4
+
5
+ ## Changed
6
+
7
+ - **Relaxed schema matching** — objects match a `CustomObject` when they contain every schema key; extra keys on the input are allowed.
8
+
9
+ ## Fixed
10
+
11
+ - Sibling-key schema redaction for falsy values (`""`, `0`, `false`) when the sibling key is present on the object.
12
+ - `ignoreBooleans` default documented to match runtime behavior (`false` — booleans are redacted unless `ignoreBooleans: true`).
13
+
14
+ ## Full changelog
15
+
16
+ See [CHANGELOG.md](../../CHANGELOG.md#121---2026-06-24).
@@ -0,0 +1,19 @@
1
+ # Release notes — v1.2.2
2
+
3
+ Type-safety and public error surface release.
4
+
5
+ ## Added
6
+
7
+ - Export `FieldRedactorError` and `FieldRedactorConfigurationError` from the package entry point.
8
+
9
+ ## Changed
10
+
11
+ - Replace heavy `any` usage with explicit JSON and redaction types (`JsonValue`, `RedactableInput`, generic `redact<T>()`, etc.).
12
+
13
+ ```typescript
14
+ import { FieldRedactor, FieldRedactorError, FieldRedactorConfigurationError } from 'field-redactor';
15
+ ```
16
+
17
+ ## Full changelog
18
+
19
+ See [CHANGELOG.md](../../CHANGELOG.md#122---2026-06-24).
@@ -0,0 +1,112 @@
1
+ # Release notes — v1.3.0
2
+
3
+ Field Redactor **1.3.0** is a feature release focused on developer experience, synchronous performance, and safer defaults for new integrations. Existing `new FieldRedactor(config)` call sites remain compatible; new APIs are opt-in.
4
+
5
+ ## Highlights
6
+
7
+ | Area | What’s new |
8
+ | --- | --- |
9
+ | **Safe construction** | `FieldRedactor.createSafe()` and `FieldRedactorConfigBuilder.buildSafeRedactor()` require explicit rules |
10
+ | **Config iteration** | `dryRun()` / `dryRunSync()` return path-level audit reports |
11
+ | **Faster sync path** | `redactSync()` / `redactInPlaceSync()` avoid per-field `Promise` overhead |
12
+ | **Lower clone cost** | Copy-on-write structural sharing for `redact()` / `redactSync()` (input still untouched by default) |
13
+ | **Onboarding** | Presets, builder API, split guides, config validation with warnings |
14
+
15
+ ## New APIs
16
+
17
+ ```typescript
18
+ import {
19
+ FieldRedactor,
20
+ FieldRedactorConfigBuilder,
21
+ presets,
22
+ validateFieldRedactorConfig,
23
+ hasExplicitRedactionRules,
24
+ EMPTY_DRY_RUN_REPORT
25
+ } from 'field-redactor';
26
+ ```
27
+
28
+ ### Recommended entry points
29
+
30
+ ```typescript
31
+ // Explicit rules — throws if no secretKeys, deepSecretKeys, fullSecretKeys, deleteSecretKeys, or customObjects
32
+ const redactor = FieldRedactor.createSafe({
33
+ ...presets.applicationLogging(),
34
+ secretKeys: [/ssn/i]
35
+ });
36
+
37
+ // Fluent builder with doc labels
38
+ const built = FieldRedactorConfigBuilder.create()
39
+ .shallow(/email/i)
40
+ .remove(/authKey/i)
41
+ .schema(metadataSchema, { name: 'metadata-entry' })
42
+ .buildSafeRedactor();
43
+ ```
44
+
45
+ ### Preview redaction without guessing
46
+
47
+ ```typescript
48
+ const { result, report } = redactor.dryRunSync(payload);
49
+ // report.redactedPaths — e.g. ['contactInfo.email']
50
+ // report.deletedPaths — e.g. ['authKey']
51
+ // report.matchedSchemas — e.g. [{ path: 'metadata[0]', schemaIndex: 0, schemaName: 'metadata-entry' }]
52
+ ```
53
+
54
+ ### Sync redaction (no async overhead)
55
+
56
+ ```typescript
57
+ const redactor = new FieldRedactor({
58
+ secretKeys: [/email/i],
59
+ syncRedactor: (val) => `REDACTED:${val}` // optional; default sync redactor works too
60
+ });
61
+
62
+ const output = redactor.redactSync(payload);
63
+ ```
64
+
65
+ ## Behavior changes
66
+
67
+ ### Copy-on-write instead of full deep clone
68
+
69
+ `redact()` and `redactSync()` no longer deep-clone the entire input up front. They traverse with copy-on-write: unmodified subtrees may **share references** with the input; only branches that are redacted or deleted are cloned.
70
+
71
+ | Before (≤ 1.2.x) | After (1.3.0) |
72
+ | --- | --- |
73
+ | Full `rfdc` clone, then redact in place on the copy | COW traversal; clone only mutated paths |
74
+ | Input never mutated | Input still never mutated when `cloneInput: true` (default) |
75
+
76
+ **If you relied on every nested object being a new reference**, compare outputs with `===` against the original or set `cloneInput: false` only when you intend in-place mutation.
77
+
78
+ ```typescript
79
+ // Restore in-place mutation semantics for redact() / redactSync()
80
+ new FieldRedactor({ secretKeys: [/email/], cloneInput: false });
81
+ ```
82
+
83
+ ### Configuration warnings
84
+
85
+ `new FieldRedactor()` without rules still redacts **all** values (legacy default). Construction now emits warnings (e.g. “All values will be redacted…”). Use `createSafe()`, the builder’s `buildSafeRedactor()`, or set `strict: true` to fail fast.
86
+
87
+ ```typescript
88
+ const warnings = validateFieldRedactorConfig({ secretKeys: [/email/] });
89
+ // or
90
+ const redactor = new FieldRedactor({ secretKeys: [/email/], strict: true });
91
+ ```
92
+
93
+ ## Migration checklist
94
+
95
+ 1. **New projects** — prefer `createSafe()` or `FieldRedactorConfigBuilder.buildSafeRedactor()` over bare `new FieldRedactor()`.
96
+ 2. **Hot paths** — switch `await redact()` to `redactSync()` when you use the default or `syncRedactor` (no async-only `redactor`).
97
+ 3. **Debugging config** — use `dryRunSync(sample)` while tuning regexes and schemas.
98
+ 4. **Presets** — spread `presets.applicationLogging()` or `presets.loggingMetadata()` as a starting point.
99
+ 5. **Reference equality** — if tests assert `result.child !== input.child` for unredacted branches, update expectations (sharing is intentional) or deep-clone before redacting if you need isolation.
100
+
101
+ ## Documentation
102
+
103
+ | Resource | Path |
104
+ | --- | --- |
105
+ | Quickstart | [README.md](../../README.md) |
106
+ | Secret key modes | [docs/guides/secret-key-modes.md](../guides/secret-key-modes.md) |
107
+ | Metadata / schemas | [docs/guides/metadata-redaction.md](../guides/metadata-redaction.md) |
108
+ | Full API reference | [docs/reference/config.md](../reference/config.md) |
109
+
110
+ ## Full changelog
111
+
112
+ See [CHANGELOG.md](../../CHANGELOG.md#130---2026-06-24).
@@ -0,0 +1,88 @@
1
+ # Release notes — v1.5.0
2
+
3
+ Field Redactor **1.5.0** is the first npm release since **1.2.0**. It publishes the accumulated work from git tags **v1.2.1** through **v1.3.0** and the former internal **2.4.0**–**2.5.1** milestones in a single consumer-facing release.
4
+
5
+ **Migration:** If you are on npm **1.2.x** or earlier, read [Migration: 1.2 → 1.5](../guides/migration-1.2-to-1.5.md) before upgrading.
6
+
7
+ ## Highlights
8
+
9
+ | Area | What’s new since npm 1.2.0 |
10
+ | --- | --- |
11
+ | **Safe construction** | `FieldRedactor.createSafe()`, `FieldRedactorConfigBuilder`, config validation |
12
+ | **Sync & performance** | `redactSync()`, copy-on-write traversal, `syncRedactor` |
13
+ | **Iteration** | `dryRun()` / `dryRunSync()` with `pathRules` rule attribution |
14
+ | **Presets & DX** | `presets.*()`, `.usePreset()`, anti-patterns guide |
15
+ | **Value-pattern defense** | Opt-in `valuePatterns` for PII embedded in free-text fields |
16
+ | **Correctness** | Relaxed schema matching, falsy sibling-key fix, unified sync/async traversal |
17
+
18
+ ## New since 1.3.0 (this release)
19
+
20
+ ### `usePreset()` and `pathRules`
21
+
22
+ ```typescript
23
+ import { FieldRedactorConfigBuilder, presets } from 'field-redactor';
24
+
25
+ const redactor = FieldRedactorConfigBuilder.create()
26
+ .usePreset(presets.applicationLogging())
27
+ .shallow(/ssn/i)
28
+ .buildSafeRedactor();
29
+
30
+ const { report } = redactor.dryRunSync(payload);
31
+ // report.pathRules → [{ path: 'email', action: 'redact', rule: 'shallow', pattern: '/email/i' }, ...]
32
+ ```
33
+
34
+ ### Value-pattern redaction
35
+
36
+ ```typescript
37
+ const emailPattern = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;
38
+
39
+ const redactor = FieldRedactor.createSafe({ valuePatterns: [emailPattern] });
40
+
41
+ const { report } = redactor.dryRunSync({
42
+ description: 'Contact alice@example.com',
43
+ note: 'no pii here'
44
+ });
45
+ // report.pathRules → [{ path: 'description', action: 'redact', rule: 'value', pattern: '...' }]
46
+ ```
47
+
48
+ **Precedence:** Schema → Opaque → Deep → Remove → Shallow → **Value-pattern** → default redactor.
49
+
50
+ ### Internal (no API change)
51
+
52
+ - Unified `ObjectRedactorTraversal` for sync in-place, copy-on-write, and async in-place redaction.
53
+ - Shared custom-object handler dispatch in `objectRedactorCustomObject.ts`.
54
+
55
+ ## Behavior changes (since 1.2.x)
56
+
57
+ | Topic | Before (≤ 1.2.x) | After (1.5.0) |
58
+ | --- | --- | --- |
59
+ | Default `redact()` clone | Full deep clone via `rfdc` | Copy-on-write; unredacted subtrees may share references with input |
60
+ | Schema matching | Exact key set | Input may contain extra keys beyond the schema |
61
+ | Falsy sibling values | Could skip redaction | Redacts `""`, `0`, `false` when sibling key is present |
62
+ | Bare `new FieldRedactor()` | Silent all-value redaction | Emits config warnings; use `createSafe()` or `strict: true` |
63
+
64
+ ## Migration checklist
65
+
66
+ 1. Read [Migration: 1.2 → 1.5](../guides/migration-1.2-to-1.5.md).
67
+ 2. Prefer `FieldRedactor.createSafe()` or `FieldRedactorConfigBuilder.buildSafeRedactor()`.
68
+ 3. Use `redactSync()` on hot paths when you do not need async `redactor`.
69
+ 4. Tune config with `dryRunSync()` and inspect `pathRules`.
70
+ 5. Add `valuePatterns` only when PII can appear in arbitrary string fields without sensitive key names.
71
+
72
+ ## Documentation
73
+
74
+ | Resource | Path |
75
+ | --- | --- |
76
+ | Migration guide | [docs/guides/migration-1.2-to-1.5.md](../guides/migration-1.2-to-1.5.md) |
77
+ | Secret key modes | [docs/guides/secret-key-modes.md](../guides/secret-key-modes.md) |
78
+ | Value-pattern redaction | [docs/guides/value-pattern-redaction.md](../guides/value-pattern-redaction.md) |
79
+ | Anti-patterns | [docs/guides/anti-patterns.md](../guides/anti-patterns.md) |
80
+ | Configuration reference | [docs/reference/config.md](../reference/config.md) |
81
+
82
+ ## Full changelog
83
+
84
+ See [CHANGELOG.md](../../CHANGELOG.md#150---2026-06-24).
85
+
86
+ ## Supersedes internal tags
87
+
88
+ Git tags `2.4.0`, `2.5.0`, and `2.5.1` were development milestones and are removed from the repository. Their content is included in this **v1.5.0** release.
package/jest.config.js CHANGED
@@ -6,7 +6,10 @@ module.exports = {
6
6
  },
7
7
  cacheDirectory: './tmp/jest-cache',
8
8
  coverageDirectory: './tmp/jest-coverage',
9
- coveragePathIgnorePatterns: ['./node_modules/', './tests/mocks/'],
9
+ coveragePathIgnorePatterns: [
10
+ './node_modules/',
11
+ './tests/mocks/'
12
+ ],
10
13
  collectCoverage: true,
11
14
  coverageThreshold: {
12
15
  global: {