Pular para o conteúdo principal

@cactus-agents/validations

Engine de regras para validação de dados do usuário. Avalia quais módulos estão pendentes com base na configuração da marca (BrandValidationModules) e no estado atual do usuário (ValidationSnapshot).

Instalação

pnpm add @cactus-agents/validations

Uso recomendado

import { fetchAllValidations } from "@cactus-agents/validations";

const result = fetchAllValidations({
config: brand.features.authValidation,
snapshot: validationSnapshot,
});

if (result.hasPending) {
console.log(result.pendingType); // "force" | "regulatory" | "global"
console.log(result.pendingModule); // "address" | "email" | "kyc" | ...
}

Conceitos

Três paths de avaliação

PathQuando ativaO que bloqueiaPrioridade
forceforceRequestKyc = true no perfilNavegação inteira (overlay bloqueante)1 (mais alta)
regulatoryshowPendingDataFlow = true no perfilNavegação inteira (overlay bloqueante)2
globalconfig.global.active = trueNavegação inteira (overlay bloqueante)3

Além desses, cada contexto (casino, sports, deposit, withdraw, etc.) é avaliado separadamente e bloqueia apenas a ação correspondente.

Módulos suportados

MóduloValidadorO que verifica
emailemail E validateEmailAt preenchidos (ambos obrigatorios)E-mail verificado
phone / smsphone E ddi preenchidos; se validateSmsAt e undefined retorna true, se definido verifica preenchidoTelefone verificado por SMS
addresszipcode + countryCode + fullAddress + city + state (5 campos)Endereço completo
docs / documentdocumentNumber + birthDate; para BRA, tambem verifica nationalities.length > 0Documentos básicos
kycisKycApprovedStatus(latestKycStatus) (validacao apos login e verificada em evaluateForceValidation, nao no predicate padrao)Selfie/documentos verificados
passwordstrongPassword é truthySenha forte definida
user_limitsse regulatoryValidationEnabled e false, retorna true (skip); se true, verifica userLimitTimeChange e userLimitLossChangeLimites prudenciais
termstermsAccepted = trueTermos aceitos
gpsgpsGranted = trueGeolocalização permitida
bank_accountse completeRegulatoryRegistrationEnabled e false, retorna true (skip); se true, verifica hasBankAccountConta bancária cadastrada

frequent flag

Quando entry.frequent = true, os módulos daquela entry são sempre avaliados como inválidos — forçando revalidação a cada ação (ex: senha para saque).

API

fetchAllValidations(input)

Função principal. Avaliacao completa que combina force + regulatory + global + contexts. Retorna FetchAllValidationsResult com hasPending, pendingType, pendingModule.

function fetchAllValidations(input: FetchAllValidationsInput): FetchAllValidationsResult;

Input:

interface FetchAllValidationsInput {
config: BrandValidationModules; // da brand config
snapshot: ValidationSnapshot; // estado do usuário
contextAmounts?: Partial<Record<ValidationContextName, number>>; // valores em centavos
}

EvaluateValidationInput

interface EvaluateValidationInput {
config: BrandValidationModules;
snapshot: ValidationSnapshot;
includeGlobal?: boolean;
enforceModules?: ValidationModuleName[];
respectFrequent?: boolean;
}

Output:

interface FetchAllValidationsResult {
force: ForceValidationDecision;
regulatory: ContextValidationDecision;
global: ContextValidationDecision;
contexts: Partial<Record<ValidationContextName, ContextValidationDecision>>;
hasPending: boolean;
pendingType: "force" | "regulatory" | "global" | null;
pendingModule: ValidationModuleName | null;
}

buildValidationSnapshot

Converte dados raw da API (formato inconsistente, campos snake_case) em ValidationSnapshot limpo:

import { buildValidationSnapshot, normalizeNationalities } from "@cactus-agents/validations";

const snapshot = buildValidationSnapshot({
isAuthenticated: true,
email: user.email,
phone: user.phone,
ddi: user.ddi,
birth_date: user.birth_date,
document: user.document,
country_data: user.country_data,
latestKyc: user.latestKyc,
address: userInfo.address,
nationalities: userInfo.nationalities,
validate_email_at: userInfo.validate_email_at,
validate_sms_at: userInfo.validate_sms_at,
// ... demais campos
});

O builder normaliza: enderecos (nested object ou string), bank account detection, regulatory flags (4 variantes de campo), termos aceitos, GPS, nacionalidades (JSON array, CSV, objects).

normalizeNationalities(raw): parseia strings de nacionalidades em diversos formatos (JSON array, CSV, objetos com value/name/code) em string[].

RawUserSnapshot: interface com todos os campos raw aceitos pelo builder.

evaluateValidationContext(input)

Avalia um contexto específico (casino, deposit, withdraw, etc.).

function evaluateValidationContext(input: EvaluateValidationInput): ValidationDecision;

evaluateForceValidation(snapshot)

Avalia se o KYC forçado está pendente. Verifica forceRequestKyc + isKycApprovedStatus + wasKycValidatedAfterLogin. Retorna ForceValidationDecision.

function evaluateForceValidation(snapshot: ValidationSnapshot): ForceValidationDecision;

resolveModulesForContext(input)

Retorna a lista de módulos que precisam ser verificados para um contexto.

function resolveModulesForContext(input: ResolveModulesInput): ValidationModuleName[];

validateModule(module, snapshot, predicates)

Valida um módulo individual contra o snapshot.

function validateModule(
module: ValidationModuleName,
snapshot: ValidationSnapshot,
predicates: Partial<Record<ValidationModuleName, ValidationPredicate>> = defaultModulePredicates,
): boolean;

Tipos principais

ValidationSnapshot

interface ValidationSnapshot {
isAuthenticated: boolean;
countryCode?: string | null;
email?: string | null;
phone?: string | null;
ddi?: string | null;
birthDate?: string | null;
nationalities?: string[];
documentNumber?: string | null;
latestKycStatus?: number | string | null;
latestKycUpdatedAt?: string | null;
kycValidatedAt?: string | null;
loginAt?: string | null;
forceRequestKyc?: boolean;
forceRequestKycReasons?: string[];
validateEmailAt?: string | null;
validateSmsAt?: string | null;
strongPassword?: boolean | number | null;
termsAccepted?: boolean;
gpsGranted?: boolean;
regulatoryValidationEnabled?: boolean;
userLimitTimeChange?: string | null;
userLimitLossChange?: string | null;
hasBankAccount?: boolean;
completeRegulatoryRegistrationEnabled?: boolean;
address?: {
zipcode?: string | null;
countryCode?: string | null;
fullAddress?: string | null;
city?: string | null;
state?: string | null;
};
}

BrandValidationModules

Config que vem da brand API (features.authValidation). Cada contexto define quais módulos estão ativos:

interface BrandValidationModules {
casino: ValidationModuleEntry;
global: ValidationModuleEntry;
sports: ValidationModuleEntry;
deposit: ValidationModuleEntry;
register: ValidationModuleEntry;
withdraw: ValidationModuleEntry;
updateData: ValidationModuleEntry;
firstDeposit: ValidationModuleEntry;
updateLimits: ValidationModuleEntry;
firstWithdraw: ValidationModuleEntry;
}

interface ValidationModuleEntry {
active: boolean;
modules: string[];
frequent: boolean;
minValue: number | null;
device: string | null;
}

ValidationContextName

type ValidationContextName =
| "casino" | "global" | "sports" | "deposit" | "register"
| "withdraw" | "updateData" | "firstDeposit" | "updateLimits" | "firstWithdraw";

ValidationModuleName

type ValidationModuleName =
| "docs" | "terms" | "email" | "phone" | "address"
| "kyc" | "gps" | "password" | "user_limits" | "bank_account"
| string;

Arquivos relevantes

ArquivoConteúdo
src/evaluate.tsFunções de avaliação (fetchAllValidations, evaluateValidationContext, evaluateForceValidation, etc.)
src/modules.tsPredicados por módulo (defaultModulePredicates)
src/snapshot.tsbuildValidationSnapshot, normalizeNationalities, RawUserSnapshot
src/types.tsTodas as interfaces e tipos
src/index.tsRe-exports públicos