Funciones empresariales
Tracelet viene equipado con varias características de alta seguridad diseñadas para casos de uso empresarial, como seguimiento militar, monitoreo de pacientes que cumple con HIPAA y logística verificada criptográficamente.
1. Cifrado de datos (SQLCipher)
Cuando Tracelet registra una ubicación en segundo plano, la almacena temporalmente en una base de datos SQLite interna antes de sincronizarla con su servidor. Si se roba un dispositivo, el acceso físico podría permitir a un atacante leer estas rutas históricas.
Tracelet resuelve este problema ofreciendo Cifrado de bases de datos en reposo mediante SQLCipher.
Cómo funciona el cifrado de datos
- Cuando habilita el indicador
encryptDatabase, la base de datos Rust SQLite subyacente se cifra instantáneamente con AES-256 a través de SQLCipher. - De forma predeterminada, Tracelet genera automáticamente una clave segura de 256 bits y la almacena de forma segura en el almacenamiento seguro nativo de la plataforma (Android Keystore/Llavero de iOS). ¡No es necesario que administres la clave manualmente!
- Todos los datos escritos en el disco se vuelven completamente ilegibles sin la clave.
- Las bases de datos existentes no cifradas se migran automáticamente a cifradas cuando la marca está habilitada.
Implementación
Para habilitar el cifrado mediante la clave segura administrada por la plataforma (recomendado):
final config = Config.balanced(
security: tl.SecurityConfig(
encryptDatabase: true, // This MUST be true to enable encryption
),
);Gestión de claves personalizadas (avanzada)
Si su aplicación prefiere administrar su propio material de claves (por ejemplo, usando flutter_secure_storage), puede proporcionar un encryptionKey personalizado. Tenga en cuenta que encryptDatabase debe ser verdadero.
// Generate a secure random key
final customKey = await tl.Tracelet.generateEncryptionKey();
await secureStorage.write(key: 'my_db_key', value: customKey);
// Pass it to Tracelet
final config = Config.balanced(
security: tl.SecurityConfig(
encryptDatabase: true,
encryptionKey: await secureStorage.read(key: 'my_db_key'),
),
);2. Gestión y verificación de seguimiento de auditoría
En logística delicada o aplicación de la ley, debe poder demostrar matemáticamente que un registro de ubicación no fue manipulado, falsificado o alterado después del hecho. Tracelet proporciona una función de Seguimiento de auditoría para crear una cadena de custodia criptográfica.
Cómo funciona la gestión de seguimiento de auditoría
Cuando AuditConfig.enabled se establece en true, Tracelet no solo guarda la latitud y la longitud. Crea un registro “similar a una cadena de bloques” para cada ubicación. El motor Rust subyacente garantiza que este proceso sea atómico e infalible:
- El bloque Génesis: Cuando el motor arranca por primera vez en un dispositivo nuevo, calcula un hash de génesis:
SHA-256("tracelet:genesis:{device_id}"). - Generación de cadenas canónicas: Para cada ubicación, Tracelet genera un formato de cadena estricto y determinista que combina el hash anterior y los datos exactos de la nueva ubicación.
- Hashing: Esta cadena canónica tiene un hash (usando SHA-256 de forma predeterminada), lo que produce
hashpara la ubicación actual. - La Cadena: Este hash se convierte en
previous_hashpara la siguiente ubicación, creando una cadena ininterrumpida. Si un atacante modifica incluso una sola coordenada de una ubicación anterior en la base de datos, el hash de esa ubicación cambiará, rompiendo toda la cadena de hashes posteriores.
Configuración
final config = Config.highAccuracy(
audit: tl.AuditConfig(
enabled: true,
hashAlgorithm: tl.HashAlgorithm.sha256,
),
);La carga útil JSON
Cuando Tracelet sincroniza estas ubicaciones con su backend, la carga útil JSON para cada ubicación contendrá directamente los campos de auditoría.
{
"device": "tracelet-example",
"locationCount": 1,
"locations": [
{
"uuid": "loc-1234-abcd",
"timestamp": "2024-01-01T00:00:00Z",
"is_moving": true,
"coords": {
"latitude": 37.774900,
"longitude": -122.419400,
"accuracy": 10.0,
"speed": 15.5,
"heading": 90.0,
"altitude": 100.0
},
"audit_hash": "a1b2c3d4e5f6...",
"audit_previous_hash": "f6e5d4c3b2a1...",
"audit_chain_index": 42
}
]
}Verificación del lado del servidor (cómo verificar el código)
Para verificar la integridad de los datos en su servidor, debe recrear la cadena canónica exacta que utiliza el núcleo de Tracelet Rust y comparar el hash resultante con el campo audit_hash en la carga útil.
1. Construya la cadena canónica
La cadena DEBE tener el formato exactamente así, separada por el carácter vertical |:
NO TRADUCIR
Reglas de formato importantes (basadas en Rust Core de Tracelet):
latitudeylongitude: formateados exactamente con 6 decimales (por ejemplo,37.774900).accuracy,speed,heading,altitude: Formateados exactamente con 2 decimales (por ejemplo,10.00).is_moving: Formateado como1(verdadero) o0(falso).
Ejemplo de cadena canónica:
f6e5d4c3b2a1...|TRACELET_AUDIT|42|loc-1234-abcd|37.774900|-122.419400|2024-01-01T00:00:00Z|10.00|15.50|90.00|100.00|12. Hash y comparar
Pase la cadena canónica construida a través de una función hash SHA-256 estándar y conviértala en una cadena hexadecimal en minúscula.
- Si su hash calculado coincide con el campo
audit_hash: se ha demostrado matemáticamente que la ubicación no está alterada. - Si no coincide: Los datos de ubicación han sido alterados. Debe marcar inmediatamente este registro e investigar el dispositivo.
3. Perfiles de precisión de ubicación (HF / LF)
Al revisar la aplicación de ejemplo Tracelet, notará botones para Precisión LF y Precisión HF. Estos se asignan directamente a los perfiles de configuración prediseñados de Tracelet.
- LF (Baja frecuencia/Baja precisión): Esto se asigna al perfil
Config.lowPower(). Restringe el motor para utilizar únicamente la triangulación de Cell-Tower y Wi-Fi (sin GPS). Es muy eficiente con la batería pero proporciona un radio de precisión más amplio. - HF (alta frecuencia/alta precisión): Esto se asigna al perfil
Config.highAccuracy(). Obliga a que se encienda el chip GPS físico, lo que proporciona una precisión de 1 a 5 metros a costa de un mayor consumo de batería.
4. Estimador de huella de carbono e informes de viaje
Tracelet incluye una utilidad CarbonEstimator incorporada. Fusiona el reconocimiento de actividad (detectar si el usuario está conduciendo, caminando o en bicicleta) con la distancia geográfica precisa para calcular las emisiones de CO₂ estimadas de un viaje. Esto es crucial para los informes de sostenibilidad, los programas de compensación de carbono o el cumplimiento de ESG (ambiental, social y de gobernanza).
como funciona
- Creas una instancia de
CarbonEstimator. - Cuando el usuario comienza a moverse (
isMoving == true), llamas astartTrip(). - Introduces cambios de actividad en tiempo real (por ejemplo, cambiar de caminar a conducir) y ubicaciones en el estimador.
- Cuando el usuario deja de moverse (
isMoving == false), llamas aendTrip()para generar unTripCarbonSummary.
Ejemplo de implementación
final carbonEstimator = tl.CarbonEstimator();
// 1. Listen for motion changes to start and end trips
Tracelet.onMotionChange((loc) {
if (loc.isMoving) {
carbonEstimator.startTrip();
} else {
final summary = carbonEstimator.endTrip();
if (summary != null) {
print('Trip ended: \${summary.totalCarbonGrams}g CO2');
print('Total Distance: \${summary.totalDistanceMeters}m');
print('Dominant Mode: \${summary.dominantMode}'); // e.g. "driving"
}
}
});
// 2. Feed Activity Recognition data to detect the transport mode
Tracelet.onActivityChange((evt) {
// Activity names map to emissions factors internally (e.g., driving vs walking)
carbonEstimator.setActivity(evt.activity.name);
});
// 3. Feed location coordinates to accumulate distance accurately
Tracelet.onLocation((loc) {
carbonEstimator.onLocationReceived(
loc.coords.latitude,
loc.coords.longitude,
);
});El TripCarbonSummary resultante se puede sincronizar con su servidor o mostrarse directamente al usuario para fomentar opciones de transporte ecológicas.
5. Configuración remota
Obtenido y aplicado de forma nativa tanto en iOS como en Android desde 3.6.2. Las versiones anteriores aceptaban remoteConfigUrl pero nunca lo recuperaban: el lado nativo volvía silenciosamente a la configuración local.
Para flotas e implementaciones grandes, a menudo es necesario cambiar el comportamiento de seguimiento (precisión, cadencia de sincronización, radio de geovalla, presupuesto de batería) sin enviar una actualización de la aplicación. La Configuración remota de Tracelet permite que el SDK extraiga un documento de configuración de su propio punto final HTTPS y lo aplique sobre la configuración local en tiempo de ejecución.
Cómo funciona la configuración remota
- Configura
remoteConfigUrl(y encabezados opcionales) en suAppConfig. - En
ready(), el SDK primero aplica la última configuración recuperada exitosamente de un caché en el dispositivo, por lo que se reanuda el reinicio en la última configuración publicada instantáneamente y sin conexión, antes de cualquier llamada de red y sin bloquearready(). - Luego, obtiene una copia nueva de su punto final en fondo y la aplica a través de la misma ruta de ejecución que
setConfig(), reiniciando el proceso de seguimiento activo solo cuando una clave relevante para el seguimiento realmente cambió. - Mantiene la configuración actualizada al volver a buscarla en la cadencia
remoteConfigRefreshInterval(en minutos).
Solo se respetan las URL HTTPS: una URL http:// se rechaza y se registra porque la configuración controla el comportamiento de seguimiento y no debe ser manipulable en tránsito.
El contrato de punto final
Su punto final responde a GET con un objeto JSON con forma de mapa de configuración de Tracelet, ya sea plano o el formulario { "geo": {…}, "app": {…}, "http": {…} } anidado que produce Config.toMap(). Sólo se anulan las claves que incluya; cualquier otra configuración mantiene su valor local.
{
"geo": { "distanceFilter": 25.0, "desiredAccuracy": 0 },
"app": { "heartbeatInterval": 120 },
"http": { "autoSync": true }
}Configuración
final config = Config.balanced().copyWith(
app: tl.AppConfig(
remoteConfigUrl: 'https://config.mycompany.com/tracelet/fleet-a.json',
remoteConfigHeaders: {'Authorization': 'Bearer $token'},
remoteConfigTimeout: 15000, // milliseconds
remoteConfigRefreshInterval: 60, // minutes
),
);| Campo | Tipo | Predeterminado | Descripción |
|---|---|---|---|
remoteConfigUrl | String? | null | Punto final HTTPS que devuelve el mapa de configuración JSON. null desactiva la configuración remota. |
remoteConfigHeaders | Map<String, String>? | null | Encabezados enviados con la recuperación (por ejemplo, token de autenticación). |
remoteConfigTimeout | int | 60000 | Recupera el tiempo de espera en milisegundos. |
remoteConfigRefreshInterval | int | 1440 | Minutos entre actualizaciones en segundo plano (con un mínimo de 15 minutos de forma nativa). 0 busca una vez y nunca se repite. |
Los valores remotos aplicados se fusionan en la configuración persistente del dispositivo y las anulaciones remotas superan a las locales. Publique solo los valores que desea que adopte cada dispositivo que obtenga esa URL: alcance por flota o por cohorte apuntando cada compilación a una URL diferente.
Observando la configuración remota aplicada desde Dart
La configuración remota se recupera y se aplica en el lado nativo. Desde 3.6.10, cada vez que se aplica una anulación remota (tanto la copia en caché restaurada en ready() como cada actualización en segundo plano), el SDK la muestra de nuevo en Dart:
Tracelet.activeConfig(y por lo tantotracelet_doctory el motor de presupuesto de batería del lado Dart) ahora refleja los valores obtenidos, en lugar de solo la última configuración que configuró localmente.- Suscríbase para reaccionar cuando llegue un cambio impulsado por el servidor:
// Callback — fires after a remote override is applied.
// Tracelet.activeConfig already reflects the new values when this fires.
Tracelet.onRemoteConfig((Config config) {
print('Remote battery budget: ${config.geo.batteryBudgetPerHour}%/hr');
});
// …or listen to the broadcast stream directly.
final sub = Tracelet.remoteConfigStream.listen((config) {
// react to the merged, now-active config
});Antes de 3.6.10, los valores remotos se aplicaban al seguimiento nativo, pero no se reflejaban en Tracelet.activeConfig, por lo que los diagnósticos aún podían mostrar el último valor establecido localmente aunque el seguimiento ya utilizara el remoto.