Pular para o conteúdo principal
Versão: Guardian v0.1.0

Pacote NPM

@surtai/guardian-web · v0.3.1

O SDK @surtai/guardian-web executa o fluxo collect() do Guardian em qualquer navegador moderno. Ele coleta sinais do dispositivo, criptografa-os localmente e retorna um payload opaco que seu backend envia ao endpoint evaluate da Surt. O SDK não faz chamadas de rede e não guarda nenhuma chave de API - com uma exceção: quando você passa um geolocationJwt opcional, collect() faz uma única chamada de melhor esforço GET /geolocation/client-ip para resolver o IP público do navegador e embuti-lo no payload. Sem geolocationJwt, collect() faz zero chamadas de rede. O JWT é um token de curta duração gerado pelo seu backend, não uma chave de API, então ainda não há chave de API no navegador.

npm install @surtai/guardian-web
Web é apenas collect

Diferente dos SDKs nativos (iOS / Android / React Native), o SDK web não expõe um método verify(). Todas as decisões de risco acontecem no lado do servidor assim que seu backend encaminha o payload. Veja Collect (Servidor para Servidor) para o fluxo completo do backend.

Uso

TypeScript
import { collect } from '@surtai/guardian-web';

// Variante 1: sem busca de IP, zero chamadas de rede.
const { payload } = await collect({ collectLocation: false });

// Variante 2: resolve o IP público do navegador para dentro do payload.
// Seu backend gera o JWT de curta duração via preflight.
const { payload: payloadWithIp } = await collect({
collectLocation: false,
geolocationJwt: jwt,
});

// Encaminhe o payload para o seu backend.
await fetch('https://your-api.com/verify-device', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId: 'user_123', payload }),
});

Seu backend gera o geolocationJwt chamando o preflight com sua chave sp_live_* - veja Autenticação. Passe o JWT para collect() apenas quando quiser resolver o IP público; caso contrário, omita-o.

Opções

OpçãoTipoObrigatórioPadrãoDescrição
collectLocationbooleanNãofalseQuando true, solicita a API de Geolocalização do navegador. É a única coisa em collect() que pode acionar um prompt de permissão.
geolocationJwtstringNão(nenhum)Quando fornecido, collect() resolve o IP público do navegador via GET /geolocation/client-ip e o embute no payload. Omita-o para pular a busca de IP (e todas as chamadas de rede).

CollectResult

interface CollectResult {
/** Payload em base64. Passe como `payload.data` na requisição evaluate mostrada abaixo. */
payload: string;
/** O que o SDK observou durante a coleta — aditivo, seguro para ignorar. */
diagnostics: {
location?: 'collected' | 'denied' | 'unavailable' | 'timeout' | 'not_requested';
networkIntel?: 'collected' | 'unavailable' | 'not_requested';
warnings: { code: string; signal: string; detail?: string }[];
};
}

O objeto diagnostics informa o que aconteceu no dispositivo — por exemplo, se a localização foi coletada ou se o usuário a negou — para que você reaja na sua interface:

const { payload, diagnostics } = await collect({ collectLocation: true });
if (diagnostics.location === 'denied') {
// peça ao usuário para ativar a localização e tente novamente
}

Veja Diagnóstico do resultado para a referência completa dos campos.

Backend: encaminhar para a Surt

Seu backend recebe o payload do navegador e o envia ao endpoint evaluate da Surt:

POST https://api.surt.com/geolocation/transactions/evaluate
Content-Type: application/json
Authorization: Bearer YOUR_SURT_API_KEY
{
"customer_id": "user_123",
"transaction_type": "login",
"transaction_name": "Sign in",
"payload": {
"type": "encrypted",
"data": "<payload de collect()>"
},
"config": {
"response": {
"address": { "type": "include" }
}
}
}

O formato da requisição, os valores suportados de transaction_type, as opções de config e o esquema de resposta são idênticos em todos os SDKs do Guardian. Veja Collect (Servidor para Servidor) para a referência completa, incluindo exemplos em Node / Java / Python.

Erros

collect() lança um único GuardianError em três condições:

import { collect, GuardianError } from '@surtai/guardian-web';

try {
const { payload } = await collect();
} catch (err) {
if (err instanceof GuardianError) {
switch (err.code) {
case 'CRYPTO_UNAVAILABLE': /* não está em um contexto seguro */ break;
case 'ENCRYPTION_FAILED': /* a criptografia falhou (raro) */ break;
case 'INVALID_OPTIONS': /* argumentos inválidos */ break;
}
}
}
CódigoSignificado
CRYPTO_UNAVAILABLEwindow.crypto.subtle está ausente. O SDK requer um contexto seguro (HTTPS ou localhost).
ENCRYPTION_FAILEDA etapa de criptografia falhou. Trate como bug: capture e reporte.
INVALID_OPTIONSO argumento de collect() não é um objeto.

Os coletores individuais (impressão digital, bateria, geolocalização, rede, etc.) nunca lançam: falham silenciosamente. Uma permissão revogada ou uma API não suportada apenas significa que o campo correspondente é omitido do payload. A busca do IP público também é de melhor esforço: se a chamada GET /geolocation/client-ip falhar ou o JWT for rejeitado, o campo de IP é simplesmente omitido e collect() ainda retorna um payload. O backend tolera payloads incompletos.

Suporte de navegador

  • Qualquer navegador moderno com window.crypto.subtle (Chrome, Edge, Firefox, Safari, Opera).
  • Contexto seguro requerido: HTTPS em produção, localhost para desenvolvimento. O SDK lança CRYPTO_UNAVAILABLE fora de um contexto seguro.
  • Geolocalização, Battery Status, NetworkInformation e outras APIs opcionais degradam com elegância quando indisponíveis.

Exemplos de frameworks

VerifyButton.tsx
import { useState } from 'react';
import { collect } from '@surtai/guardian-web';

export function VerifyButton({ userId }: { userId: string }) {
const [loading, setLoading] = useState(false);

const handleClick = async () => {
setLoading(true);
try {
const { payload } = await collect({ collectLocation: false });
await fetch('/api/verify-device', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId, payload }),
});
} finally {
setLoading(false);
}
};

return (
<button onClick={handleClick} disabled={loading}>
{loading ? 'Verificando...' : 'Continuar'}
</button>
);
}

Diferenças em relação aos SDKs nativos

@surtai/guardian-web@surtai/guardian-rn / iOS / Android
Método verify()NãoSim
Método collect()Sim (única API)Sim
Inicialização no nível do appNenhumainitialize(options)
Contexto de cliente / transaçãoDefinido pelo seu backendCarregado nas claims do JWT gerado pelo backend
Chave de API no clienteNãoNão (usa um JWT gerado pelo backend, não uma chave de API)
Chamadas de rede do SDKNenhuma (a menos que geolocationJwt seja passado)Sim
Verificação de integridade do dispositivoNão (sem equivalente no navegador)Sim
Estado por cliente persistenteNão (sem estado entre chamadas)Não

Web é intencionalmente enxuto: uma única função estática que produz um payload criptografado. A associação ao cliente, os metadados da transação e as decisões acontecem todos no seu backend.