Skip to main content

Telemetry, Device Registration, Tier-3 Support Short Code & Canary QA

Every installation of a Flutter application embedding the OTA runtime generates an anonymous unique UUID v4 (client_id) on its first launch. This mechanism powers auto-discovery of devices in the backend, Tier-3 Technical Support triage using an 8-character short code, and Canary QA device enrollment.

1. Generation & Persistence of client_id (state.json)​

On first native boot, the Rust engine (UpdaterState) generates a random UUID v4 (e.g., "6959347f-ec8d-4b50-8562-a9562443ac3b") and writes it to a local JSON file (state.json or patches_state.json):

PlatformPaths Inspected by TkOtaPush.readClientId()
Android/data/user/0/<package>/files/shorebird_updater/state.json (probed via Directory.systemTemp.parent + /files)
iOS<Sandbox>/Library/Application Support/shorebird_updater/state.json and fallback <Sandbox>/Documents/shorebird_updater/state.json
Custom / TestAny path passed through optional appSupportDirectoryPath

Example structure of shorebird_updater/state.json:

{
"client_id": "6959347f-ec8d-4b50-8562-a9562443ac3b",
"release_version": "1.0.0+13",
"queued_events": []
}

2. Reading Device Identity & Tier-3 Support Short Code​

Rather than forcing users to dictate all 36 characters of a raw UUID over a support call, TkOtaPush derives an 8-character Tier-3 Support Short Code:

  • Strips - hyphens from client_id and converts to uppercase.
  • Takes the first 8 characters and prefixes with # (e.g., "6959347f-ec8d-4b50-8562-a9562443ac3b" becomes "#6959347F").

Using Identification Methods​

final ota = TkOtaPush.instance;

// 1. Read full UUID v4
final String? clientId = await ota.readClientId();
// -> "6959347f-ec8d-4b50-8562-a9562443ac3b"

// 2. Read 8-character Support Code
final String? shortCode = await ota.readShortSupportCode();
// -> "#6959347F"

// 3. Read full OtaDeviceIdentity object
final OtaDeviceIdentity? identity = await ota.readDeviceIdentity();
if (identity != null) {
print(identity.toJson());
// {
// "client_id": "6959347f-ec8d-4b50-8562-a9562443ac3b",
// "short_support_code": "#6959347F",
// "release_version": "1.0.0+13",
// "track": "stable",
// "current_patch_number": 2
// }
}

Ready-to-Use Widget for Settings / Support Screens​

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:tk_ota_push/tk_ota_push.dart';

class OtaSupportDiagnosticTile extends StatelessWidget {
const OtaSupportDiagnosticTile({super.key});


Widget build(BuildContext context) {
return FutureBuilder<OtaDeviceIdentity?>(
future: TkOtaPush.instance.readDeviceIdentity(),
builder: (context, snapshot) {
final identity = snapshot.data;
final shortCode = identity?.shortSupportCode ?? 'Not initialized';
final fullUuid = identity?.clientId ?? 'Waiting for OTA engine';
final patchLabel = identity?.currentPatchNumber != null
? 'Patch #${identity!.currentPatchNumber}'
: 'Original Store Binary';

return Card(
margin: const EdgeInsets.symmetric(vertical: 8),
child: ListTile(
leading: const Icon(Icons.phonelink_setup, color: Colors.teal),
title: Text(
'Support Code: $shortCode • $patchLabel',
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(
'UUID: $fullUuid',
style: const TextStyle(fontFamily: 'monospace', fontSize: 11),
),
trailing: IconButton(
icon: const Icon(Icons.copy, size: 18),
tooltip: 'Copy full UUID',
onPressed: identity == null
? null
: () {
Clipboard.setData(ClipboardData(text: identity.clientId));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Code ${identity.shortSupportCode} (${identity.clientId}) copied!',
),
),
);
},
),
),
);
},
);
}
}

3. Automatic Device Registration & Canary QA Whitelist​

When a device makes its first request to POST /api/v1/patches/check or POST /api/v1/patches/events, the server records the terminal into the fleet registry with:

  • Its client_id and #8CAR short code
  • Its release_version, platform (android / ios), and arch (aarch64 / arm)
  • Its resolved country (X-Country-Code, CF-IPCountry, X-Geo-Country, or query country)

In the Device Fleet & Support dashboard (/support) of the TkushPatch Web Console, search #6959347F to:

  1. Assign a friendly name to the handset (e.g., "QA Lab — iPhone 12 Pro").
  2. Enroll the device in the Canary QA Whitelist (allowed_client_ids_csv): the handset receives targeted or experimental patches before wide public rollout.
  3. Acknowledge a Rollback Alert (rollback_acknowledged_at).

4. Telemetry Payload & Event Lifecycle (PatchEvent)​

When an event occurs, the Rust engine writes it to queued_events inside state.json (preventing event loss if offline during app boot), then forwards it to POST /api/v1/patches/events.

JSON Payload Sent to POST /api/v1/patches/events​

{
"event": {
"event_id": "c4f1d820-9a1b-4e3c-8c7a-123456789abc",
"app_id": "com.saramoney.retail",
"arch": "aarch64",
"client_id": "6959347f-ec8d-4b50-8562-a9562443ac3b",
"type": "__patch_install__",
"patch_number": 2,
"platform": "android",
"release_version": "1.0.0+13",
"timestamp": 1731150000,
"failure_category": null,
"message": null
}
}

Deduplication via event_id​

Every event generates a unique UUID v4 event_id upon instantiation (PatchEvent::new in updater/library/src/events.rs). If the server's 201 Created acknowledgment is lost on an unstable mobile connection and the phone retries delivery, the backend safely deduplicates using event_id.