> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ancestraldev.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Hardware Identification (HWID): Machine Binding in Avalex

> Learn how Avalex uses hardware identifiers to bind licenses to specific machines, enforce per-machine activation limits, and prevent unauthorized sharing.

A Hardware Identifier (HWID) is a stable, machine-specific string that your application computes at runtime and submits with every license validation request. Avalex records which HWIDs have been bound to a given license and uses that record to enforce per-machine activation limits. This prevents a customer from sharing a single license key across an unlimited number of devices — once all available HWID slots are filled, validation requests from unrecognised hardware return `valid: false`.

## Generating a Good HWID

A reliable HWID must be **stable across reboots and software updates** and **unique enough** to distinguish individual machines. The recommended approach is to read one or more immutable hardware values from the operating system and pass them through a SHA-256 hash. Hashing ensures the raw hardware value (which may be sensitive) never leaves the machine, and produces a fixed-length string suitable for network transmission.

**Good hardware sources to combine:**

* **Motherboard UUID** — embedded in firmware, unique per board, rarely changes
* **CPU ID** — processor-level identifier, consistent across reboots
* **`/etc/machine-id`** — generated once at OS installation on Linux, persistent across updates
* **`IOPlatformUUID`** — Apple's platform-level UUID on macOS, stable for the life of the hardware

<Warning>
  Avoid using mutable values like **hostname** or **username** alone — these can be changed by the user at any time, causing HWID drift and spurious validation failures. If you must incorporate them, combine them with at least one immutable hardware value so that a single change does not invalidate the computed identifier.
</Warning>

### Python Example

The function below detects the current operating system and reads the most reliable available hardware source, then returns a 32-character uppercase hex string derived from a SHA-256 hash.

```python theme={null}
import hashlib, platform, subprocess

def get_hwid() -> str:
    system = platform.system()
    raw_id = ""
    try:
        if system == "Windows":
            raw_id = subprocess.check_output(
                "wmic csproduct get uuid", shell=True
            ).decode().split('\n')[1].strip()
        elif system == "Linux":
            with open("/etc/machine-id") as f:
                raw_id = f.read().strip()
        elif system == "Darwin":
            raw_id = subprocess.check_output(
                "ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID",
                shell=True
            ).decode().split('"')[3].strip()
    except Exception:
        raw_id = platform.node() + platform.machine()
    return hashlib.sha256(raw_id.encode()).hexdigest().upper()[:32]
```

Call `get_hwid()` once at application startup, cache the result in memory, and pass it in the `hwid` field of every `POST /licenses/validate` request.

## The HWID Slot System

Each license has a `maxHwids` field set when the license is issued. This controls how many distinct hardware identifiers can be bound to a single license key.

* When a validation request arrives with an **unrecognised HWID**, Avalex checks whether the number of currently bound HWIDs is below `maxHwids`. If there is room, the new HWID is registered and the check passes.
* When all slots are **full**, any request from a new, unrecognised HWID returns `valid: false`, regardless of whether the license is otherwise valid.
* A HWID that is **already bound** does not consume a new slot — repeated validations from the same machine always succeed (subject to other checks).
* If `maxHwids` is `null`, the license accepts an unlimited number of hardware identifiers.

## Admin Unbinding

There are legitimate reasons for a customer to switch machines — hardware failure, a computer upgrade, or an IT-managed device replacement. In these situations, an admin can remove a specific HWID binding directly from the **Admin Portal**, freeing that slot for the customer's new machine. No license reissue is required. Navigate to the license record, open the bound HWIDs list, and delete the entry you want to remove.
