Device Provisioning Pattern

Context

FlexGalaxy.AI is a multi-tenant APaaS where each account (tenant) manages its own fleet of IoT devices. The platform uses multiple backend systems — ThingsBoard for device management and telemetry, hawkBit for OTA updates, and DotID for platform API authentication — each with its own device identity and credential model.

Device provisioning is not a single event. A device may go through multiple provisioning stages across its lifecycle — from factory assembly to field deployment — each with different identity proofs, credential requirements, and target accounts.

The Provisioning Service is a dedicated microservice, separate from DeviceAdmin, exposed at api.flexgalaxy.com/provisioning/v1/. DeviceAdmin delegates enrollment to the Provisioning Service and provides the device management API on top.

Provisioning Scenarios

Devices are provisioned at different stages of their lifecycle, by different actors, into different accounts:

Scenario 1: Factory Provisioning (Controller)

A core controller is produced and flashed with basic firmware at the controller factory. This is the earliest provisioning step.

Controller Factory
     │
     │  POST /provisioning/v1/enroll
     │  {
     │    "scenario": "factory",
     │    "device_type": "controller",
     │    "manufacturer": "syrius",
     │    "serial": "CTRL-2024-001",
     │    "firmware_version": "bootloader-1.0"
     │  }
     │  + mTLS (manufacturer CA cert)
     │
     ▼
Provisioning Service
     ├── ThingsBoard: create device (basic profile, factory account)
     ├── hawkBit: create target (eligible for firmware updates)
     └── Return: MQTT credentials + DDI token

At this stage:

  • The controller is registered under the manufacturer’s account

  • Only basic firmware and connectivity credentials are issued

  • No DotID M2M client (not yet a business API participant)

  • The controller can receive firmware updates via hawkBit DDI

Scenario 2: Assembly Provisioning (Robot)

Once the controller is assembled into a complete robot, the robot requests re-provisioning to install full software and transition to an operational profile.

Assembly Line
     │
     │  POST /provisioning/v1/enroll
     │  {
     │    "scenario": "assembly",
     │    "device_type": "amr",
     │    "parent_serial": "CTRL-2024-001",
     │    "serial": "AMR-X1-2024-001",
     │    "capabilities": ["navigation", "picking", "charging"]
     │  }
     │  + mTLS (same manufacturer CA cert)
     │
     ▼
Provisioning Service
     ├── ThingsBoard: upgrade device profile (controller → AMR)
     ├── hawkBit: update target attributes (capabilities, type)
     ├── DotID: create M2M OIDC client (robot can now call platform APIs)
     └── Return: full credentials (MQTT + DDI + M2M API)

At this stage:

  • The device record is upgraded from “controller” to “AMR” with full capabilities

  • A DotID M2M client is created (the robot can now call FlexGalaxy business APIs)

  • The device may still be under the manufacturer’s account (pre-delivery)

Scenario 3: Field Provisioning (Customer Deployment)

When a device arrives at a customer site (warehouse, shopping mall), it is provisioned into the customer’s account. This also covers MDM-style provisioning for tablets and PDAs.

Customer Site (warehouse, mall)
     │
     │  POST /provisioning/v1/enroll
     │  {
     │    "scenario": "field",
     │    "claim_token": "tok-abc-123",
     │    "device_type": "pda",
     │    "serial": "PDA-2024-042"
     │  }
     │  (or mTLS for robots being transferred)
     │
     ▼
Provisioning Service
     ├── Validate claim token → resolve customer account
     ├── ThingsBoard: create device (or transfer from manufacturer account)
     ├── hawkBit: update target tenant
     ├── DotID: create/update M2M client (scoped to customer account)
     └── Return: operational credentials for customer environment

Field provisioning handles:

  • Robots transferred from manufacturer — device moves from manufacturer account to customer account, credentials are rotated

  • Tablets / PDAs — MDM-style enrollment using claim tokens (QR code scan)

  • Constrained sensors — pre-shared tokens distributed during installation

  • Cross-account — devices may span different accounts, organizations, and permission scopes

Scenario Summary

Scenario

Actor

Account

Identity

Credentials Issued

Factory

Manufacturer

Manufacturer account

mTLS (manufacturer CA)

MQTT + DDI

Assembly

Manufacturer

Manufacturer account

mTLS (manufacturer CA)

MQTT + DDI + M2M API

Field (robot)

Customer / operator

Customer account

mTLS or claim token

MQTT + DDI + M2M API (rotated)

Field (PDA/tablet)

Operator on-site

Customer account

Claim token (QR)

MQTT + DDI + M2M API

Field (sensor)

Installer

Customer account

Pre-shared token

MQTT + DDI

Pattern

Device Identity Verification

Different provisioning scenarios use different identity proofs:

Device Class

Identity Method

Verification

Robots (AMR, cleaning)

X.509 client certificate

Validate against manufacturer’s subordinate CA

PDAs / tablets

Claim token + device serial

Token issued during physical setup (QR code)

Constrained sensors

Pre-shared access token

Token distributed during installation

Gateways

X.509 or claim token

Depends on gateway type

X.509 Certificate Chain

For robot-class devices, FlexGalaxy.AI uses a certificate chain:

FlexGalaxy Root CA
└── Manufacturer Subordinate CA (e.g., Syrius Robotics CA)
    └── Device Certificate (e.g., AMR-X1 SN-2024-001)
  • The platform trusts manufacturer CAs registered through the developer portal

  • Each device presents its certificate during mTLS enrollment

  • The Provisioning Service validates the chain and extracts the manufacturer and serial number from the certificate’s Subject DN

Claim Tokens

For devices that cannot do mTLS (PDAs, tablets, sensors):

1. Operator generates claim tokens in bulk via API or StarGate
2. Tokens are printed as QR codes or loaded onto devices during setup
3. Device presents claim token during enrollment
4. Token maps to account + device type + priority + expiry
5. Token is consumed (single-use)

Tenant Resolution

The Provisioning Service resolves which ThingsBoard tenant (FlexGalaxy account) the device belongs to:

Identity Method

Tenant Resolution

X.509 cert (factory/assembly)

Manufacturer CA → manufacturer account

X.509 cert (field transfer)

Claim token overrides → customer account

Claim token

Token contains account ID directly

Pre-shared token

Token was issued for a specific account

Backend System Registration

After identity verification and tenant resolution, the Provisioning Service creates or updates device records in backend systems:

Step

System

API Call

Result

1

ThingsBoard

POST /api/device or PUT /api/device/{id}

Device ID, MQTT credentials

2

hawkBit (via OTAForge)

POST /rest/v1/targets or update attributes

Controller ID, DDI security token

3

DotID

Create OIDC client (if applicable)

Client ID, client secret (M2M)

All systems use the same device identifier (device_id), enabling cross-system correlation.

Credential Types Issued

Credential

System

Purpose

Rotation

MQTT access token

ThingsBoard

Telemetry ingestion, device mgmt

Via Provisioning Service

DDI security token

hawkBit (via OTAForge proxy)

OTA update polling

Via Provisioning Service

OIDC client credentials

DotID (Keycloak)

Business API access (client_credentials grant)

Via DotID API

X.509 cert (if used)

mTLS

Enrollment identity

Manufacturer-managed

Device Lifecycle

┌──────────┐     ┌────────────┐     ┌──────────┐     ┌──────────┐     ┌───────────────┐
│ Unmanaged │────►│  Factory   │────►│ Assembled │────►│  Field   │────►│ Decommissioned│
│           │     │ Provisioned│     │ Upgraded  │     │  Active  │     │               │
└──────────┘     └────────────┘     └──────────┘     └──────────┘     └───────────────┘
                       │                  │                │
                       │ failure          │ failure        │ suspend
                       ▼                  ▼                ▼
                 ┌────────────┐     ┌────────────┐   ┌──────────┐
                 │  Rejected  │     │  Rejected  │   │ Suspended │
                 └────────────┘     └────────────┘   └──────────┘

State

Description

Unmanaged

Physical device or component, not yet enrolled

Factory Provisioned

Controller registered with basic firmware, manufacturer account

Assembled / Upgraded

Full robot with complete capabilities, manufacturer account

Field Active

Deployed at customer site, customer account, fully operational

Suspended

Temporarily disabled (e.g., lease expired, policy violation)

Decommissioned

Removed from all systems, credentials revoked

Rejected

Enrollment failed (invalid identity, unknown manufacturer)

Account Transfer

When a device moves from manufacturer to customer (or between customers):

  1. New enrollment request with scenario: "field" + claim token or mTLS

  2. Provisioning Service transfers ThingsBoard device to new tenant

  3. hawkBit target attributes updated (new tenant context)

  4. DotID M2M client rotated (new account scope)

  5. Old credentials revoked, new credentials issued

  6. Emit device.transferred event to Kafka

Decommissioning

When a device is decommissioned:

  1. Revoke ThingsBoard credentials (disable device)

  2. Remove hawkBit target (no more OTA updates)

  3. Delete DotID M2M client (revoke API access)

  4. Archive telemetry data (retention policy applies)

  5. Emit device.decommissioned event to Kafka

API Surface

Operation

Endpoint

Description

POST /provisioning/v1/enroll

Enroll or re-provision a device

GET /provisioning/v1/devices/{id}

Get provisioning status and history

POST /provisioning/v1/devices/{id}/transfer

Transfer device to a different account

POST /provisioning/v1/devices/{id}/rotate-credentials

Rotate credentials across all systems

POST /provisioning/v1/devices/{id}/suspend

Suspend a device

POST /provisioning/v1/devices/{id}/reactivate

Reactivate a suspended device

DELETE /provisioning/v1/devices/{id}

Decommission a device

POST /provisioning/v1/claim-tokens

Generate claim tokens (batch)

GET /provisioning/v1/claim-tokens?account={id}

List unused claim tokens

Dependencies

Service

Relationship

ThingsBoard

Creates/transfers device records and MQTT credentials

OTAForge (hawkBit)

Creates/updates targets and DDI security tokens

DotID (Keycloak)

Creates M2M OIDC clients

Org Service

Resolves account/tenant context, org hierarchy

Consumed By

Consumer

Usage

DeviceAdmin

Delegates enrollment, transfer, and decommission operations

Devices

Enroll during factory, assembly, or field deployment

StarGate

Admin UI for managing provisioning, generating claim tokens

Applications

Query device provisioning status

Consequences

Benefits

  • Multi-scenario provisioning — same service handles factory, assembly, and field enrollment with different identity proofs and credential sets

  • Account transfer — devices can move between accounts (manufacturer → customer) with credential rotation and audit trail

  • Consistent identity — same device ID across ThingsBoard, hawkBit, and DotID enables cross-system correlation

  • Separation from DeviceAdmin — provisioning logic is complex (compensating transactions, multi-scenario, account transfer) and benefits from being an independent service with its own lifecycle

Trade-offs

  • Multi-system coordination — provisioning depends on ThingsBoard, hawkBit, and DotID all being available; enrollment fails if any is down

  • Compensating transactions — if one system fails mid-enrollment, partial records must be cleaned up

  • Custom service — this is a FlexGalaxy-specific service, not an off-the-shelf component; it must be built and maintained