Custom Patterns
Extend @secured-ai/core with your own regex-based entity types to detect domain-specific identifiers.
Overview
The built-in set of 44 entity types covers common PII, but every domain has its own identifiers. @secured-ai/core lets you add custom regex patterns at runtime so you can detect things like internal employee IDs, order numbers, policy references, or any proprietary format your application uses.
Custom patterns are managed by the Custom Pattern Engine, which is always active regardless of your engines configuration.
Adding a custom pattern
Use addPattern() on a PrivacyClient instance. Patterns take effect immediately — no re-initialisation required.
import { PrivacyClient } from '@secured-ai/core'
const client = new PrivacyClient({
baseUrl: 'https://dev-api.securedai.com',
sdkAccessToken: import.meta.env.VITE_SECURED_SDK_ACCESS_TOKEN,
})
await client.initialize()
client.addPattern({
name: 'employee-id',
pattern: /\bEMP-\d{6}\b/,
entityType: 'CUSTOM',
confidence: 0.95,
})CustomPattern interface
interface CustomPattern {
name: string // unique identifier for this pattern (used to remove it)
pattern: RegExp // the regex to match against
entityType: EntityType // which entity type to assign matched text
confidence?: number // optional confidence score (default: 0.85)
}Pattern names must be unique across all registered custom patterns. Adding a pattern with a duplicate name overwrites the existing one.
Using a custom EntityType name
The EntityType union includes 'CUSTOM' as a catch-all, but you can use any of the 44 built-in types to classify your custom pattern's matches under an existing category. For example, a company's internal reference number could be classified as 'REFERENCE_ID' so it gets obfuscated along with other reference identifiers.
client.addPattern({
name: 'internal-ref',
pattern: /\bREF-[A-Z]{2}-\d{4}\b/,
entityType: 'REFERENCE_ID', // uses a built-in sensitive type
confidence: 0.92,
})Real-world example: employee IDs
Imagine your application processes HR documents that contain employee IDs in the format EMP-XXXXXX. You want these redacted before the document is sent to an external API.
import { PrivacyClient } from '@secured-ai/core'
const client = new PrivacyClient({
baseUrl: 'https://dev-api.securedai.com',
sdkAccessToken: import.meta.env.VITE_SECURED_SDK_ACCESS_TOKEN,
replacementPools: {
CUSTOM: ['EMP-000001', 'EMP-000002', 'EMP-000003'],
},
})
await client.initialize()
client.addPattern({
name: 'employee-id',
pattern: /\bEMP-\d{6}\b/,
entityType: 'CUSTOM',
confidence: 0.97,
})
const { processed, sessionId } = await client.obfuscate(
'Performance review for EMP-482910 (manager: EMP-103847).'
)
console.log(processed)
// 'Performance review for EMP-000001 (manager: EMP-000002).'
// Restore when needed
const { restored } = await client.restore(processed, sessionId)
console.log(restored)
// 'Performance review for EMP-482910 (manager: EMP-103847).'Multiple custom patterns
You can register as many patterns as needed:
client.addPattern({
name: 'policy-number',
pattern: /\bPOL-\d{4}-[A-Z]{3}\b/,
entityType: 'REFERENCE_ID',
confidence: 0.95,
})
client.addPattern({
name: 'claim-id',
pattern: /\bCLM\d{8}\b/,
entityType: 'CASE_NUMBER',
confidence: 0.93,
})
client.addPattern({
name: 'vehicle-vin',
pattern: /\b[A-HJ-NPR-Z0-9]{17}\b/,
entityType: 'REFERENCE_ID',
confidence: 0.88,
})Removing a custom pattern
Use removePattern() with the pattern's name. It returns true if the pattern was found and removed, false otherwise.
const removed = client.removePattern('employee-id')
console.log(removed) // truePatterns can be removed and re-added at any time without affecting the rest of the engine pipeline.
Custom patterns and obfuscation
Custom pattern matches are included in detect() results and will be obfuscated by obfuscate() only if their entityType is in the sensitive types list. If you use entityType: 'CUSTOM', note that 'CUSTOM' is not in the default sensitive types — use a built-in sensitive type like 'REFERENCE_ID', 'CASE_NUMBER', or 'MEDICAL_ID' if you want automatic obfuscation.
Alternatively, use detect() + obfuscate() with a manual entity filter for full control:
const scan = await client.detect(text)
// include all entities, including CUSTOM type
const allEntities = scan.entities
// build obfuscation manually
const result = await client.obfuscate(text)