export const DEFAULT_USER_PASSWORD = '123456' export const MIN_PASSWORD_LENGTH = 8 export const MIN_FULL_NAME_LENGTH = 2 export const USERNAME_PATTERN = /^[a-z0-9._-]{3,32}$/ export const PHONE_NUMBER_PATTERN = /^\+?\d{8,15}$/ export type UserRole = 'super_admin' | 'staff' export function normalizeUsername(value: string) { return value.trim().toLowerCase() } export function normalizeFullName(value: string) { return value.trim() } export function normalizePhoneNumber(value: string) { const trimmed = value.trim() if (!trimmed) { return '' } const hasPlusPrefix = trimmed.startsWith('+') const digitsOnly = trimmed.replace(/\D/g, '') return hasPlusPrefix ? `+${digitsOnly}` : digitsOnly } export function isValidPhoneNumber(value: string) { return PHONE_NUMBER_PATTERN.test(normalizePhoneNumber(value)) } export function isValidUsername(value: string) { return USERNAME_PATTERN.test(normalizeUsername(value)) } export function hasValidFullName(value: string) { return normalizeFullName(value).length >= MIN_FULL_NAME_LENGTH } export function isUserRole(value: string | null | undefined): value is UserRole { return value === 'super_admin' || value === 'staff' } export interface AuthUser { id: string username: string fullName: string phoneNumber: string | null role: UserRole isActive: boolean mustChangePassword: boolean needsPasskeySetup: boolean passkeyCount: number createdAt: string lastLoginAt: string | null } export interface ManagedUser extends AuthUser { createdBy: string | null } export interface PublicContact { id: string fullName: string phoneNumber: string role: UserRole } export interface PasskeySummary { id: string label: string createdAt: string lastUsedAt: string | null deviceType: 'singleDevice' | 'multiDevice' backedUp: boolean } export function needsUserOnboarding( user: Pick | null | undefined ) { return Boolean(user && (user.mustChangePassword || user.needsPasskeySetup)) } export function getDefaultAuthenticatedPath( user: Pick ) { if (needsUserOnboarding(user)) { return '/security' } return user.role === 'super_admin' ? '/management/users' : '/security' }