Configuration
validatePassword takes a single flat options object — every field is optional. This page shows policy presets and patterns for shaping the configuration to your context.
Basic Configuration
import { validatePassword } from '@sentinel-password/core'
const result = validatePassword('mypassword', { minLength: 8 })See the ValidatorOptions type for the full list of fields.
Configuration Presets
Minimal (Low Security)
For low-risk applications:
const minimal = { minLength: 6 }Balanced (Medium Security)
A reasonable default for consumer apps:
const balanced = {
minLength: 8,
maxLength: 128,
requireUppercase: true,
requireDigit: true,
}Strict (High Security)
For enterprise or sensitive workflows:
const strict = {
minLength: 12,
maxLength: 128,
requireUppercase: true,
requireLowercase: true,
requireDigit: true,
requireSymbol: true,
maxRepeatedChars: 2,
// checkSequential, checkKeyboardPatterns, checkCommonPasswords default to true
}Maximum (Very High Security)
const maximum = {
minLength: 16,
maxLength: 128,
requireUppercase: true,
requireLowercase: true,
requireDigit: true,
requireSymbol: true,
maxRepeatedChars: 2,
personalInfo: [], // populate with user fields when available
}Defaults already sit between Minimal and Balanced
With no options at all, validatePassword enforces minLength: 8, maxLength: 128, maxRepeatedChars: 3, and runs the sequential, keyboard-pattern, and common-password checks. The require* flags are off by default.
Environment-Based Configuration
import type { ValidatorOptions } from '@sentinel-password/core'
// Match the standard NODE_ENV values. Anything unrecognized — including
// undefined — falls through to the strictest (production) preset, which is
// the right fail-safe default for a security check.
const getConfig = (env: string | undefined): ValidatorOptions => {
if (env === 'development') return { minLength: 4 }
if (env === 'test') return { minLength: 4 }
return {
minLength: 12,
requireUppercase: true,
requireDigit: true,
requireSymbol: true,
}
}
const config = getConfig(process.env.NODE_ENV)Dynamic Configuration
Tighten the policy for privileged users and feed identity into personalInfo:
interface User {
email: string
firstName: string
lastName: string
role: 'user' | 'admin'
}
const getUserConfig = (user: User): ValidatorOptions => {
const base: ValidatorOptions = {
minLength: 8,
requireUppercase: true,
requireDigit: true,
personalInfo: [user.email, user.firstName, user.lastName].filter(Boolean),
}
if (user.role === 'admin') {
return { ...base, minLength: 16, requireSymbol: true }
}
return base
}Sharing Configuration With the Client
Define the policy once and use it both in the React hook and on the server:
// shared/password-policy.ts
import type { ValidatorOptions } from '@sentinel-password/core'
export const PASSWORD_POLICY: ValidatorOptions = {
minLength: 12,
requireUppercase: true,
requireLowercase: true,
requireDigit: true,
requireSymbol: true,
}// client
import { usePasswordValidator } from '@sentinel-password/react'
import { PASSWORD_POLICY } from '../shared/password-policy'
const { password, setPassword, result } = usePasswordValidator(PASSWORD_POLICY)// server
import { validatePassword } from '@sentinel-password/core'
import { PASSWORD_POLICY } from '../shared/password-policy'
const result = validatePassword(req.body.password, {
...PASSWORD_POLICY,
personalInfo: [req.body.email, req.body.name],
})See the Server-Side Usage guide for full Express/Fastify/NestJS examples.
Debouncing (React Hook)
usePasswordValidator debounces validation by default — control timing with debounceMs:
import { usePasswordValidator } from '@sentinel-password/react'
// Default — 300ms after typing stops
usePasswordValidator({ minLength: 8 })
// Slower debounce
usePasswordValidator({ minLength: 8, debounceMs: 500 })
// Instant validation on every keystroke
usePasswordValidator({ minLength: 8, debounceMs: 0, validateOnChange: true })Localized Feedback
Pass a messages template map keyed by stable MessageCode, or a formatMessage callback for full i18n-library integration. Both are options on ValidatorOptions:
import { validatePassword, type MessageCode } from '@sentinel-password/core'
// Pattern 1 — partial template overrides
const result = validatePassword(password, {
minLength: 12,
messages: {
'length.tooShort': 'La contraseña debe tener al menos {minLength} caracteres',
} satisfies Partial<Record<MessageCode, string>>,
})
// Pattern 2 — plug into react-intl / i18next / FormatJS
validatePassword(password, {
formatMessage: (code, params, defaultMessage) =>
intl.formatMessage({ id: `sentinelPassword.${code}`, defaultMessage }, params),
})The Internationalization guide covers eight stable codes, {placeholder} interpolation, re-localizing characterTypes via params.missingTypes, and ICU pluralization through formatMessage. The legacy lookup-table workaround (mapping English strings to translations) keeps working because the default English templates are stable across patch and minor releases.
Best Practices
Don't Over-Restrict
Balance security with usability:
// Too restrictive — blocks reasonable passwords
{
minLength: 32,
maxLength: 32,
requireUppercase: true,
requireLowercase: true,
requireDigit: true,
requireSymbol: true,
}
// Better balance
{
minLength: 12,
maxLength: 128,
requireUppercase: true,
requireDigit: true,
requireSymbol: true,
}Always Pass personalInfo When You Have It
The check is essentially free and catches JohnSmith2024! for ["John", "Smith"]:
validatePassword(password, {
...policy,
personalInfo: [user.email, user.firstName, user.lastName].filter(Boolean),
})Match Requirements to Risk
| Surface | Suggested preset |
|---|---|
| Blog comments, throwaway accounts | Minimal |
| E-commerce, consumer apps | Balanced |
| Banking, healthcare, B2B SaaS | Strict |
| Admin panels, root credentials | Maximum |
Show Requirements Up Front
Don't make users guess the rules — surface them in the UI before they type, and make sure the UI copy matches the policy you actually enforce.
PasswordInput always validates against the defaults (minLength: 8, common-password / sequential / keyboard-pattern checks on, no required character types). For any stricter policy, use usePasswordValidator so the requirements you describe in the UI are the same ones being checked:
import { usePasswordValidator } from '@sentinel-password/react'
const policy = {
minLength: 12,
requireUppercase: true,
requireDigit: true,
requireSymbol: true,
}
function PasswordField() {
const { password, setPassword, result } = usePasswordValidator(policy)
return (
<div>
<label htmlFor="pw">Create Password</label>
<p id="pw-help">Must be 12+ characters with uppercase, digit, and symbol</p>
<input
id="pw"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
aria-describedby="pw-help"
aria-invalid={result && !result.valid ? true : undefined}
/>
{result?.feedback.suggestions.map((msg, i) => (
<p key={i}>{msg}</p>
))}
</div>
)
}