import { ShieldLabs, evaluateIdentification, webhooks } from '@shieldlabs-ai/node';
const shieldlabs = new ShieldLabs({ apiKey: process.env.SHIELDLABS_API_KEY! });
// One identification authorizes one action. This in-memory set keeps the example short; in
// production, claim request IDs atomically in Redis or your database (see "Apply a policy").
const usedRequestIds = new Set<string>();
function claimRequestId(requestId: string): boolean {
if (usedRequestIds.has(requestId)) return false;
usedRequestIds.add(requestId);
return true;
}
// 1. Call this with the requestId the browser sent together with the signup form.
export async function allowSignup(requestId: string): Promise<boolean> {
// Scoring is asynchronous: this waits (up to 10 s by default) until the verdict is stored.
const identification = await shieldlabs.identifications.get(requestId);
// 2. Missing, reused, stale, rate-limited, automated or dangerous: refuse.
const firstUse = identification !== null && claimRequestId(identification.request_id);
const verdict = evaluateIdentification(identification, { isReplay: () => !firstUse });
return verdict.ok;
}
// 3. Call this with the raw body and the X-Shield-Signature header of a webhook delivery.
export function handleWebhook(rawBody: string | Uint8Array, signatureHeader: string | null): void {
const event = webhooks.constructEvent(
rawBody,
signatureHeader,
process.env.SHIELDLABS_WEBHOOK_SECRET!,
);
if (event.event_type === 'identification.scored') {
console.log(event.data.request_id, event.data.risk_score, event.data.detection_flags.vpn);
}
}