Su primera evaluación
Su backend consulta a FingerTrackID sobre una acción, aquí un inicio de sesión, y recibe la respuesta en la misma llamada. En modo shadow nada cambia en su producto: usted guarda la respuesta junto a la decisión que su sistema ya toma.
Antes de empezar, necesita:
- el
key_idde una credencial de servidor, y su secreto ya en su gestor de secretos (alta de la empresa); - Node.js 24.16 o posterior en la serie 24, o 26.1 o posterior. Otro lenguaje también sirve, mediante las reglas de firma.
1. Instale y compruebe
Sección titulada «1. Instale y compruebe»Fije la versión exacta. self-check reproduce el
vector de firma público en el Node.js que lo ejecuta,
para que sepa que la firma funciona antes de tocar una credencial. No necesita ninguna.
El paquete no tiene ninguna dependencia en tiempo de instalación ni script de instalación. Compare
el integrity de su lockfile con el del registro.
npm install --save-exact @fingertrackid/server@0.1.2npx --no fingertrackid-server self-checknpm view @fingertrackid/server@0.1.2 dist.integrity2. Cree el cliente una sola vez
Sección titulada «2. Cree el cliente una sola vez»Cree un solo cliente cuando arranque el backend, leyendo ambos valores por nombre desde el entorno. El secreto proviene de su gestor de secretos: nunca de un archivo del repositorio, de un argumento de comando ni de un asistente de IA.
Un valor ausente o mal formado lanza FtidConfigurationError con un code fijo y nunca reproduce
el valor. Emita una alerta y mantenga su producto funcionando sin FingerTrackID.
import { createFtidServerClient, type FtidServerClient } from '@fingertrackid/server'
export let ftid: FtidServerClient | null = nulltry { ftid = createFtidServerClient({ keyId: process.env.FTID_KEY_ID ?? '', secretHex: process.env.FTID_HMAC_SECRET_HEX ?? '', })} catch (error) { // Alert on it, and keep the product running without FingerTrackID. logger.error('ftid.configuration_error', { code: (error as { code?: string }).code })}3. Evalúe el inicio de sesión
Sección titulada «3. Evalúe el inicio de sesión»Después de sus propias comprobaciones, llame a assess con la etiqueta que
eligió para este momento, un seudónimo con clave de la persona y el token que el
Web SDK generó para esta acción.
Mientras el Web SDK no esté en su frontend, envíe null como token: la llamada funciona y la
evaluación vuelve sin puntuación.
assess nunca lanza una excepción después del arranque. Cada desenlace es un resultado, y ninguno
debería detener su inicio de sesión:
result.kind |
Qué hace su backend |
|---|---|
ASSESSED |
Guárdelo; su propia política decide |
INVALID_INPUT |
Corrija la llamada; no se envió nada |
PROBLEM |
Siga result.problem.category |
UNAVAILABLE |
Mantenga su decisión; es posible que la solicitud se haya guardado |
UNEXPECTED_RESPONSE |
Mantenga su decisión; informe el correlationId |
// After your own checks. `ftid` is null after a configuration error: the login goes on.const result = await ftid?.assess({ tag: 'login', subjectRef: pseudonymOf(user), // a keyed pseudonym, never an email or tax ID eventContextToken: body.ftidToken ?? null, eventContextExpiresAt: body.ftidTokenExpiresAt ?? null,})
if (result?.kind === 'ASSESSED') { await storeBesideYourDecision(result.assessment)} else if (result !== undefined) { // Log identifiers and verdicts only: never the secret, the token or the body. logger.warn('ftid.assess', { kind: result.kind, severity: result.severity })}4. Lea la respuesta
Sección titulada «4. Lea la respuesta»Tres campos contienen la respuesta:
assessment_statusesCOMPLETEDsolo cuando había evidencia reciente del navegador. Sin token, con el perfil de producción gestionado actual, esINCONCLUSIVE.trust_scoreva de 0 a 100, más alto es mejor, y solo existe enCOMPLETED.nullsignifica sin puntuación: nunca 0.recommended_actiones una recomendación. Nunca bloquea ni permite nada por sí sola.
Compruebe que external_event_id y tag sean los que envió, y guarde la respuesta tal como la
recibió. Todos los campos están en la página de respuesta.
{ "schema_version": "event-assessment.v1.1", "assessment_id": "01996f2a-0000-7000-8000-000000000401", "assessment_version": 1, "supersedes_assessment_id": null, "business_event_id": "01996f2a-0000-7000-8000-000000000402", "external_event_id": "login_20260904_000002", "tag": "login", "assessment_status": "INCONCLUSIVE", "retryable": false, "trust_score": null, "device_intelligence_snapshot_id": null, "device_intelligence_snapshot_version": null, "device_id": null, "device_match_confidence": null, "evidence_coverage": 0, "data_freshness": { "evidence_cutoff_at": "2026-09-04T12:00:00.105Z", "oldest_required_observed_at": null, "maximum_required_age_ms": 300000, "all_required_fresh": false }, "signals": [ { "signal_code": "ANTI_FINGERPRINTING", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "BOT_AUTOMATION", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "BROWSER_PRIVACY_BRAVE", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "BROWSER_PRIVACY_SAFARI", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "BROWSER_PRIVACY_SAMSUNG_INTERNET", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "BROWSER_SPOOFING", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "DEVICE_MULTI_USER", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "EMULATED_ENVIRONMENT", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "NETWORK_HOSTING", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "NETWORK_PROXY", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "NETWORK_TOR", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "NETWORK_VPN", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null }, { "signal_code": "PRIVATE_BROWSING", "channel": "WEB", "signal_state": "NOT_EVALUATED", "applicability": "APPLICABLE", "source": "DERIVED", "detector_version": "unavailable-web-detectors.v1", "detector_confidence": null, "observed_at": null, "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": null, "not_evaluated_reason_code": "COLLECTOR_NOT_LOADED", "applicability_reason_code": null } ], "limitation_codes": [ "COLLECTOR_NOT_LOADED", "REQUIRED_EVIDENCE_MISSING" ], "reason_codes": [ "REQUIRED_EVIDENCE_MISSING" ], "recommended_action": "MONITOR", "recommendation_basis": "INSUFFICIENT_EVIDENCE", "policy_version": "production-detectors-01996f29-4d2c-7b18-9e6a-3f0c8d1b5a72-login", "fallback_policy_version": "production-observation-fallback-v2", "ruleset_version": "d95-detectors.v1", "signal_catalog_version": "web-detectors-v3", "feature_schema_version": "configured-assessment-features.v1", "resolver_version": "first-party-installation-v1", "sdk_version": null, "provider_versions": [], "evidence_cutoff_at": "2026-09-04T12:00:00.105Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "expires_at": "2026-09-04T12:01:00.143Z", "correlation_id": "01996f2a-1111-7000-8000-000000000405"}{ "schema_version": "event-assessment.v1.1", "assessment_id": "01996f2a-0000-7000-8000-000000000101", "assessment_version": 1, "supersedes_assessment_id": null, "business_event_id": "01996f2a-0000-7000-8000-000000000102", "external_event_id": "login_20260904_000001", "tag": "login", "assessment_status": "COMPLETED", "retryable": false, "trust_score": 100, "device_intelligence_snapshot_id": "01996f2a-0000-7000-8000-000000000103", "device_intelligence_snapshot_version": 2, "device_id": "dev_AZlvKYwefUqy8GqePF17GA", "device_match_confidence": null, "evidence_coverage": 100, "data_freshness": { "evidence_cutoff_at": "2026-09-04T12:00:00.105Z", "oldest_required_observed_at": "2026-09-04T11:59:57.318Z", "maximum_required_age_ms": 300000, "all_required_fresh": true }, "signals": [ { "signal_code": "ANTI_FINGERPRINTING", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "SDK", "detector_version": "ftid-anti-fingerprinting.v2", "detector_confidence": 0.4, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "BOT_AUTOMATION", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "SDK", "detector_version": "ftid-bot-automation.probe.v3", "detector_confidence": 0.6, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "BROWSER_PRIVACY_BRAVE", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "SDK", "detector_version": "ftid-browser-privacy-brave.v1", "detector_confidence": 0.8, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "BROWSER_PRIVACY_SAFARI", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "SDK", "detector_version": "ftid-browser-privacy-safari.v1", "detector_confidence": 0.5, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "BROWSER_PRIVACY_SAMSUNG_INTERNET", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "SDK", "detector_version": "ftid-browser-privacy-samsung-internet.v1", "detector_confidence": 0.6, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "BROWSER_SPOOFING", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "SDK", "detector_version": "browser-spoofing-coherence.v2", "detector_confidence": 0.5, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "DEVICE_MULTI_USER", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "SERVER_CONTEXT", "detector_version": "ftid-device-multi-user.v1", "detector_confidence": 0.5, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "EMULATED_ENVIRONMENT", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "SDK", "detector_version": "emulated-environment-coherence.v2", "detector_confidence": 0.3, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "NETWORK_HOSTING", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "PROVIDER", "detector_version": "ftid-network-hosting.v1", "detector_confidence": 0.6, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "NETWORK_PROXY", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "PROVIDER", "detector_version": "ftid-network-proxy.v1", "detector_confidence": 0.4, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "NETWORK_TOR", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "PROVIDER", "detector_version": "ftid-network-tor.v1", "detector_confidence": 0.9, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "NETWORK_VPN", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "PROVIDER", "detector_version": "ftid-network-vpn.v1", "detector_confidence": 0.4, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null }, { "signal_code": "PRIVATE_BROWSING", "channel": "WEB", "signal_state": "NOT_DETECTED", "applicability": "APPLICABLE", "source": "SDK", "detector_version": "ftid-private-browsing.storage-mode.v2", "detector_confidence": 0.5, "observed_at": "2026-09-04T11:59:57.318Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "freshness_ms": 2825, "not_evaluated_reason_code": null, "applicability_reason_code": null } ], "limitation_codes": [], "reason_codes": [ "NO_ADVERSE_INDICATOR_MATCH" ], "recommended_action": "MONITOR", "recommendation_basis": "EVALUATION", "policy_version": "production-detectors-01996f29-4d2c-7b18-9e6a-3f0c8d1b5a72-login", "fallback_policy_version": "production-observation-fallback-v2", "ruleset_version": "d95-detectors.v1", "signal_catalog_version": "web-detectors-v3", "feature_schema_version": "configured-assessment-features.v1", "resolver_version": "first-party-installation-v1", "sdk_version": "0.2.1", "provider_versions": [ "asn-reputation.v1", "cloud-ranges.v1", "icloud-private-relay.v1", "ip2proxy-lite-px2.v1", "tor-exit.v1", "x4b-vpn.v1" ], "evidence_cutoff_at": "2026-09-04T12:00:00.105Z", "evaluated_at": "2026-09-04T12:00:00.143Z", "expires_at": "2026-09-04T12:01:00.143Z", "correlation_id": "01996f2a-1111-7000-8000-000000000105"}5. Compruebe la credencial real
Sección titulada «5. Compruebe la credencial real»check envía una evaluación en modo shadow, con la etiqueta integration_check y sin token del
navegador, e imprime el resultado. El secreto proviene solo de FTID_HMAC_SECRET_HEX o de la
entrada estándar, nunca de un argumento.
--no hace que npx ejecute solo la copia que instaló su proyecto, nunca un paquete con el mismo
nombre del registro.
your-secret-manager read ftid-hmac-secret | FTID_KEY_ID=<key_id> npx --no fingertrackid-server checkSiguientes pasos
Sección titulada «Siguientes pasos»- Instale el Web SDK para que las evaluaciones incluyan evidencia del navegador y una puntuación.
- Concilie un resultado desconocido con
result.operation, enviando de nuevo los mismos bytes. - Informe sus acciones y resultados, para que la consola pueda compararlos con la recomendación.
- Entregue la integración a un agente de programación con IA, con el archivo de integración y el servidor MCP.