@@ -8,12 +8,16 @@ import type { CustomPiiPattern } from '@/lib/guardrails/pii-entities'
88const logger = createLogger ( 'PIIValidator' )
99
1010/**
11- * Compute the explicit entity list to send Presidio. When custom patterns are
12- * present we must always send an explicit list (even empty) so the server detects
13- * only the requested built-ins plus the custom entities — never "all". With no
14- * built-ins and no patterns, `undefined` preserves the legacy "detect all" default.
11+ * Entity list for the batch (data-retention) paths, where an empty selection with
12+ * custom patterns means "redact ONLY these custom patterns" (the user unchecked
13+ * every built-in entity). An explicit empty array is sent so the server detects
14+ * only the custom entities, never "all". With neither, `undefined` preserves the
15+ * legacy "detect all" default.
16+ *
17+ * The guardrails single-text path uses the opposite convention — empty selection
18+ * means "detect all" — so it does NOT use this helper (see {@link analyze}).
1519 */
16- function resolveEntities (
20+ function resolveBatchEntities (
1721 entityTypes : string [ ] ,
1822 patterns ?: CustomPiiPattern [ ]
1923) : string [ ] | undefined {
@@ -83,7 +87,11 @@ async function analyze(
8387 language : string ,
8488 patterns ?: CustomPiiPattern [ ]
8589) : Promise < AnalyzerSpan [ ] > {
86- const entities = resolveEntities ( entityTypes , patterns )
90+ // Guardrails convention: an empty selection means "detect all". Sending no
91+ // `entities` keeps that, and the server still runs the custom recognizers under
92+ // detect-all — so a custom pattern augments the built-in detectors, never
93+ // silently replaces them.
94+ const entities = entityTypes . length > 0 ? entityTypes : undefined
8795
8896 // boundary-raw-fetch: internal call to the Presidio analyzer service via PII_URL
8997 const response = await fetch ( `${ PII_URL } /analyze` , {
@@ -114,7 +122,7 @@ async function analyzeBatch(
114122 language : string ,
115123 patterns ?: CustomPiiPattern [ ]
116124) : Promise < AnalyzerSpan [ ] [ ] > {
117- const entities = resolveEntities ( entityTypes , patterns )
125+ const entities = resolveBatchEntities ( entityTypes , patterns )
118126
119127 // boundary-raw-fetch: internal call to the Presidio analyzer service via PII_URL
120128 const response = await fetch ( `${ PII_URL } /analyze_batch` , {
@@ -188,7 +196,7 @@ async function redactBatch(
188196 language : string ,
189197 patterns ?: CustomPiiPattern [ ]
190198) : Promise < string [ ] | null > {
191- const entities = resolveEntities ( entityTypes , patterns )
199+ const entities = resolveBatchEntities ( entityTypes , patterns )
192200
193201 // boundary-raw-fetch: internal call to the Presidio combined redact service via PII_URL
194202 const response = await fetch ( `${ PII_URL } /redact_batch` , {
0 commit comments