Skip to main content

Identity

:::info Status Implemented. Source: docs/device-management-module-architecture.md §1, §3, §5e, §6.0; fastapi-backend/core/device_claim.py, fastapi-backend/core/device_registry.py. :::

Identity answers exactly one question: which physical unit is this? Nothing more. It is established once, at manufacture and claim, and never changes for the life of the unit.

ConceptLives inChanged byNever changed by
Identitydevices.device_uid, MQTT client id, topic pathmanufacture / claimrebinding, membership changes, approval

This is the first of five concepts this system keeps strictly separate — see Terminology for the full table and Device Architecture for why.

The identity chain

Inventory precedes device. A serial that was never imported into device_inventory cannot be claimed (unknown_serial) — the single control that stops an unmanifested unit from entering the fleet. The factory never holds a device_secret; manufacturing produces identifiers only, and the manifest is checked (row count + checksum vs. the purchase order), not trusted blindly.

hardware_revision is captured at import time — it's what binds which firmware/config a unit can accept later, and can't be inferred after the fact from the serial alone. MAC may be null for parts that can't read it at manufacture time; it's then bound at first claim, which weakens the cross-check below to serial-only for that unit (a per-batch decision, never a silent fallback).

Claim-time cross-validation (§6.1a)

A hard acceptance criterion, not a soft mitigation — every field must agree with the inventory row or the claim is rejected outright:

Claim is also where the inventory transition IN_STOCK → ALLOCATED happens — the step the rest of the lifecycle (verify/activate/approve) depends on as a precondition without itself triggering it. This does not prove the hardware is genuine — a clone holding a stolen serial/MAC pair would also pass (closed properly only by a secure-element key, noted as an open per-batch decision in the source doc) — but it does mean counterfeiting requires stealing a specific sold unit's identity rather than inventing plausible ones.

Identity vs. authentication

Identity (device_uid lookup) and authentication (device_secret verified via bcrypt; a per-device broker credential for MQTT) are the first two of five distinct questions this system asks on every request — see Device Authorization for the full chain and why passing an earlier one never implies the later ones.

/announce vs. /claim

POST /device-registry/announcePOST /device-registry/claim
Authnone (IP rate-limited)user JWT
Who calls itan unprovisioned unit, on its ownthe installer/buyer
On a manifest matchcreates/refreshes a PENDING row, links inventory — no credentials returnedopens ownership + assignment, releases broker credentials, stays PENDING
On no matchrecorded in unmanifested_announcements, no device rowrejected (unknown_serial)

/announce polls every 30 seconds until claimed — the only polling endpoint in the system, because a pre-claim unit has no open session to push anything to. Full endpoint list: Device Management module.

An unmatched announcement lands in unmanifested_announcements — a queue for humans, never a device state: either an unimported manifest (fix: import it) or a counterfeit (fix: investigate). Nothing is promoted automatically.