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

# Licensing and Enrollment

> Activate a Coreflux broker with an online code or a signed license, enroll it in an organization, and inspect tier limits

## Unlock the plan you bought

A Coreflux broker always starts. With no license it runs as **Community**. A signed license — obtained online with an activation code, or installed offline as a file — is what raises the plan, artifact budget, and premium features.

> [!TIP]
>
> **Like a signed ticket versus a door code.** An activation code is the door code: the broker exchanges it once for a signed ticket (the license) and keeps that ticket. An offline file *is* the ticket, already signed for the broker host. Either way, the broker checks the ticket itself — losing internet does not lock you out.

### When to use this

* **Start a 30-day Growth trial** — register at [portal.coreflux.org](https://portal.coreflux.org), then activate the license on your broker
* **Manage your fleet** of brokers in the same portal
* **Activate a running broker** with a `CFLX-…` code, without restarting
* **Install a signed license** on an air-gapped host using the hardware fingerprint
* **Enroll** the broker into a Coreflux organization so federated logins can bind to that org
* **Check usage and limits** from `$SYS/Coreflux/License` or the ops [`GET /license`](/latest/mqtt-broker/operational-endpoints#license-status) endpoint

Licensing and enrollment are **separate**. A license sets the plan. Enrollment binds the broker to an organization. You can license a broker without enrolling it.

***

The sections below cover the two license paths, the MQTT commands, environment variables, and how to watch status.

## Quick Start

**Activate online**

Paste an activation code on a running broker. Limits apply immediately — no restart.

```bash wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
-activateLicense CFLX-XXXX-XXXX-XXXX
```

Get the code by registering at [portal.coreflux.org](https://portal.coreflux.org) (including a 30-day Growth-type license). The broker exchanges the code with the licensing authority, verifies the signed lease, and republishes `$SYS/Coreflux/License`. The code is used once and is not written to disk; the signed lease is what survives a restart.

On a broker you cannot reach over MQTT, set `COREFLUX_ACTIVATION_CODE` in the **process** environment and start (or restart) the broker instead.

**Install a signed file**

For air-gapped hosts, print the broker host's fingerprint, send it to Coreflux, and install the signed file you get back:

```bash wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
./CorefluxMQTTBroker --show-fingerprint
./CorefluxMQTTBroker --load-license /path/to/license.jws
```

`--load-license` verifies the file and stages it under the data directory as `config/license.jws` before MQTT starts. On a running broker, publish `-loadLicense` with either a path **on the broker host** or the compact JWS text itself (the usual path from Coreflux HUB).

**Enroll in an organization**

Enrollment binds this broker to a Coreflux organization. It does not change the plan. Stage a one-shot token (`et_…`, typically valid for about 10 minutes):

```bash wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
-enroll et_…
```

The broker exchanges the token in the background and never echoes it in the command reply. Until enrollment succeeds the broker still starts: local users work; federated logins that need an org binding are refused.

## Plans

Three plans. With no license and no activation code, the broker is **Community**. The broker does **not** start a trial on its own.

### 30-day Growth trial

To try Growth features, **register at [portal.coreflux.org](https://portal.coreflux.org)**. That issues a **30-day Growth-type license**. Activate it on your broker the same way as any other license (`-activateLicense` / `COREFLUX_ACTIVATION_CODE`, or a signed file). When the 30 days end, the broker reverts to Community like any other expired license.

Use the same portal to **manage your fleet of brokers**. This page does not walk through portal screens — open the portal and follow the flow there.

The same account is how [Coreflux HUB](/hub/account-and-fleet) lists that fleet and connects with an access token. The broker accepts the token only after enrollment has set its organization and [OIDC bearer authentication](/latest/mqtt-broker/oidc-authentication) is enabled. License activation and that MQTT check are separate: a valid license does not by itself turn token login on.

> [!NOTE]
>
> A **Cloud Trial** on [Installation](/latest/quick-start/installation) is a hosted broker and HUB Coreflux runs for you. A Growth trial from the portal is a **license** you apply to a broker you install (Docker, package, or binary).

A 30-day trial uses the **Growth** column. Paid plans keep the same limits until the license expires.

| Feature | Community | Growth | Enterprise |
| - | - | - | - |
| Artifact budget | 24 | 100 | 1 000 |
| Connectors | 3 | 5 | Unlimited |
| MQTT Bridge | No | Yes | Yes |
| MCP | No | Yes | Yes |
| LLM / Agent | No | Yes | Yes |
| Video input / output | No | Yes | Yes |
| RBAC / topic access control | No | Yes | Yes |
| Cluster | No | No | Yes |
| Max connections (display) | 10 000 | 10 000 | 10 000 |

Custom ACL rules (`-addRule`) require Growth or Enterprise. Shipped default rules always apply. See [RBAC with LoT Rules](/latest/lot-language/rules/rbac).

A `TYPE LLM` connector counts toward the connector cap. A `DEFINE AGENT` needs the same Growth or Enterprise license and does not take a connector slot. License usage reports agents separately from connectors. See [AI Connectors and Agents](/latest/lot-language/routes/ai-routes).

### Artifact budget

Models, Actions, and Panels each cost **1**. Python scripts cost **2**. When the budget is full, new definitions are refused with a message that names the limit.

When a license expires (past expiry plus any offline grace), the broker reverts to **Community**. Existing artifacts keep running; new artifacts, advanced connectors, and new RBAC rules are blocked.

***

## How the broker picks a license

On boot the broker uses the **first** source that succeeds:

1. **Inline signed token** — process env `COREFLUX_LICENSE_TOKEN` (a compact JWS)
2. **License file path** — process env `COREFLUX_LICENSE_FILE` (for a read-only mount)
3. **Working file** — `config/license.jws` in the [data directory](/latest/mqtt-broker/secrets-and-env#config-root)
4. **Online activation** — process env `COREFLUX_ACTIVATION_CODE`
5. **Community** — nothing of the above

A verified token is staged to `config/license.jws` so later restarts can load it without the network. An online lease then refreshes about once a day.

> [!WARNING]
>
> Licensing reads the **process** environment at boot (`Docker environment:`, systemd `Environment=`, Kubernetes `env:`). It does **not** read the LoT `.env` file you manage with `-setEnv` / `GET ENV`. Put `COREFLUX_ACTIVATION_CODE` in the process environment, not only in the data-directory `.env`.

***

## Commands

Publish to `$SYS/Coreflux/Command` and subscribe to `$SYS/Coreflux/Command/Output`. The same verbs work from [Coreflux HUB Command Console](/hub/system/command-console) and the System Config **License** tab. See [Broker Commands](/latest/mqtt-broker/commands#license).

| Command | Alias | Permission | What it does |
| - | - | - | - |
| `-activateLicense <code>` | `--activate-license` | `SystemConfiguration` | Exchanges a `CFLX-…` code for a lease and applies it immediately. No restart. |
| `-loadLicense <jws-or-path>` | `--load-license` | `CommandCall` | Verifies a signed license (compact JWS text, or a path on the broker host) and stages `config/license.jws`. |
| `-refreshLicense` | `--refresh-license` | `CommandCall` | Forces one online lease refresh. Refused when the broker holds no lease. |
| `-enroll <et_…>` | `--enroll` | `CommandCall` | Stages a single-use enrollment token. The exchange runs in the background. |

### Activate

```bash wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
-activateLicense CFLX-XXXX-XXXX-XXXX -requestId license-1
```

```json wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "success": true,
  "command": "ActivateLicense",
  "requestId": "license-1",
  "message": "Activated: Growth (lic_…), hard seat, expires 2027-04-09. Limits applied now — no restart needed.",
  "data": {}
}
```

On refusal the broker `message` names the remedy (unknown code, no free seat, authority unreachable). The activation code is redacted from broker logs and the audit trail.

### Load a signed license

A compact JWS is treated as the license itself. Anything else is treated as a path on the **broker** filesystem:

```bash wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
-loadLicense /path/to/license.jws
-loadLicense eyJhbGciOiJFUzI1NiIsInR5cCI6IkNGTFhMSUMi.….<payload>.<signature>
```

```json wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "success": true,
  "command": "LoadLicense",
  "message": "Signed license verified and stored at <config>/license.jws",
  "data": {}
}
```

HUB and other remote clients send the JWS text because they cannot write a file on the broker host. Strip wrapping whitespace before you send it — a compact JWS contains none, but files often arrive with a trailing newline.

> [!NOTE]
>
> Brokers that predate JWS-text `-loadLicense` treat the token as a path and reply `License file not found: eyJ…`. Update the broker, or install on the host with `--load-license /path/to/license.jws`.

### Refresh an online lease

The online lease refreshes on a 24-hour timer. Use `-refreshLicense` when a plan change or revocation should apply now:

```bash wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
-refreshLicense
```

Refused when this broker holds no online lease — activate first, or install an offline file instead.

### Enroll

```bash wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
-enroll et_…
```

The reply confirms the token was staged; it never contains the token. Treat enrollment as done when `$SYS/Coreflux/License` shows `Enrollment.Enrolled` as `true` or `Enrollment.BoundOrg` set to the organization id — Coreflux HUB shows **Enrolled** in that case. `Enrollment.Pending` going false is not enough. While enrollment is still pending, `Enrollment.Reason` names the remaining problem.

#### When the platform can't be reached

If egress to `brokers.coreflux.org` is blocked, the broker keeps serving. Licensing and local users are unaffected. Only federated logins wait for `BoundOrg`. Each platform call times out after 15 seconds, so startup isn't delayed.

A lease enrollment with no answer retries at the next licence refresh (daily, or now with `-refreshLicense`). An `et_…` token with no answer is kept and retried with backoff (5 seconds, doubling up to every 5 minutes) while the token is valid. A new token, or pressing **Enroll** in Coreflux HUB, is tried at once.

`Enrollment.Reason` says the platform couldn't be reached, and the broker logs one warning instead of an error per attempt.

#### When the credential is revoked

If the broker's Fleet row is deleted, the broker is disconnected, or the organization is deleted, the broker logs *Platform no longer recognises this credential* and keeps serving.

If it holds an online lease, it renames the file to `credential.json.revoked` and enrolls again with the lease within seconds. The portal only accepts that for a broker waiting in Fleet, so a disconnected broker doesn't rejoin on its own.

Without a lease, replace or remove the credential and supply a new `et_…` token.

***

## Startup flags

These flags are processed at process start (see [Startup Options](/latest/mqtt-broker/startup-options)):

| Option | Long form | Description |
| - | - | - |
| `-showFingerprint` | `--show-fingerprint` | Print the broker host's hardware fingerprint and exit. Send that value to Coreflux to be issued an offline license. Does not start MQTT. |
| `-loadLicense` | `--load-license` | Stage a signed license file as `config/license.jws` before MQTT starts. |
| `-enroll` | `--enroll` | Stage a single-use `et_…` token for the startup exchange. Also accepted on `$SYS/Coreflux/Command` while running. |

***

## Environment variables

Set these on the **broker process**. Restart after changing them unless you use `-activateLicense` / `-enroll` on a live broker instead.

| Variable | Role |
| - | - |
| `COREFLUX_ACTIVATION_CODE` | Online activation (`CFLX-…`). Also turns **enrollment** on. |
| `COREFLUX_LICENSE_TOKEN` | Inline signed JWS. Wins over a file on disk. |
| `COREFLUX_LICENSE_FILE` | Path to a signed `.jws` file (read-only mounts). |
| `COREFLUX_FLEET_METRICS` | `off`, `false`, or `0` stops an enrolled broker sending [fleet performance metrics](#fleet-performance-metrics). Unset leaves them on. This wins over the Portal switch. |
| `DO_NOT_TRACK` | `1` turns off fleet performance metrics and the anonymous install census. |

A broker onboarded from Coreflux HUB needs none of these. Enrollment also turns on at boot when `config/enrollment/credential.json` exists (from `-enroll`) or `config/license.jws` holds an online lease for this instance (from `-activateLicense`). A successful `-activateLicense` turns it on immediately, without a restart.

There is no `COREFLUX_ENROLLMENT_TOKEN` environment variable. Deliver the token with `--enroll` / `-enroll`, or write it to `{data directory}/config/enrollment-token`.

Allow outbound HTTPS to `https://license.coreflux.org` for activation and refresh, and to `https://brokers.coreflux.org` for enrollment.

***

## Fleet performance metrics

An enrolled broker sends a host description, one metrics point per minute, and up to 25 grouped error reports on the same enrollment heartbeat (every 300 seconds by default). No extra connection is opened. A broker that is not enrolled sends nothing. The Coreflux Portal charts the metrics on that broker's page.

The host description includes the process start time, operating system and version, architecture, .NET version, container and orchestrator, core count, cgroup CPU quota and memory limit, and cluster role and size. It does not include a hostname, IP address, user name, or file path.

Each minute includes CPU (average and peak), working set and managed heap, garbage-collection pause share and thread-pool queue peak, connected clients, connects and disconnects, messages and bytes in and out (with per-second peaks), refused CONNECTs, ACL denials, rate-limit refusals, route and cluster drops, and route, action, model, and Python errors. It also includes the session count, the retained-message count, the ten routes with the most errors.

Error signatures are scrubbed before they leave the broker. Numbers become `#`. GUIDs and hex ids become `<id>`. Anything in single or double quotes becomes `'…'`. The text is cut at 200 characters. Topics and payloads are never sent. Each signature is named by the route, action, model, or script that failed.

Errors are grouped by kind, not by source, so 100 connectors with the same fault send one report. Each report lists the sources that hit it (up to 50, busiest first) with a count, and adds:

* A category (`comms`, `config`, `auth`, `resource`, `script`, `internal`, or `device`), a severity, whether the broker retries on its own, and a short hint when the broker recognizes the error.
* The exception type and the first broker code frame. For an action, the LoT line that failed.
* For a connector, its type and name. Never its address.

Transient connector errors, such as timeouts and dropped sockets, fold into one **Connection unstable** report per connector type, with the number of reconnects. It is a warning while reads still succeed, and becomes an error once a source has gone more than two report intervals without a good read. The whole error block stays under about 24 KB.

The heartbeat also reports why the previous broker process stopped: `graceful`, `signal` (for example a Kubernetes rollout or Ctrl-C), `unhandled` (with the exception type), or `unknown` (killed, out of memory, or power loss), with its start time and uptime. This needs a persistent data directory. On a container without one it stays empty.

While the platform is unreachable, the broker keeps up to 60 unsent minutes and sends them when the platform answers again. Older minutes are dropped.

Fleet performance metrics are on by default. The Coreflux Portal has a per-broker switch. The broker learns that choice from the heartbeat response, within one interval. These settings on the broker always win over the Portal:

1. `COREFLUX_FLEET_METRICS=off` (or `false` or `0`).
2. `DO_NOT_TRACK=1`.
3. `"Enrollment": { "Metrics": { "Enabled": false } }` in the broker configuration.

`COREFLUX_TELEMETRY` affects only the anonymous install census. It does not change fleet performance metrics. The counters behind these metrics are also exposed on the local [`/metrics`](/latest/mqtt-broker/operational-endpoints#metrics) endpoint, whether fleet metrics are on or off.

***

## Watch license status

The broker publishes the full status **retained** on:

```
$SYS/Coreflux/License
```

The same status is served on **`GET /license`** on the [operational endpoints](/latest/mqtt-broker/operational-endpoints#license-status) listener (default port `9100`). HTTP property names are camelCase; the samples below match the retained topic. Ops HTTP is unauthenticated — do not expose that port to the public internet.

Community brokers still publish the topic, so you can read `Tier`, `EffectiveLimits`, `CurrentUsage`, `Fingerprint`, and `Enrollment`.

```json wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "LicensedTo": "N/A",
  "ExpiresUtc": null,
  "IsActive": false,
  "Tier": "Community",
  "Fingerprint": "…",
  "FingerprintSource": "machine-id",
  "EffectiveLimits": {
    "MaxArtifacts": 24,
    "MaxRoutes": 3,
    "MaxConnections": 10000
  },
  "CurrentUsage": {
    "ArtifactCount": 4,
    "Routes": 1
  },
  "Enrollment": { "Pending": false, "Reason": null, "Enrolled": false, "BoundOrg": null }
}
```

An activated Growth license looks like:

```json wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "LicensedTo": "Acme Corp",
  "ExpiresUtc": "2027-04-09T00:00:00Z",
  "IsActive": true,
  "Tier": "Growth",
  "Plan": "growth",
  "Activation": {
    "Mode": "online",
    "BindingOk": true,
    "Online": {
      "IsLease": true,
      "SeatMode": "hard",
      "LeaseExpiresUtc": "2026-09-28T00:00:00Z"
    }
  },
  "Enrollment": { "Pending": false, "Reason": null, "Enrolled": false, "BoundOrg": null }
}
```

Those two samples are licensed (or not) without an organization binding. A finished enrollment on a current broker looks like this:

```json wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{ "Pending": false, "Reason": null, "Enrolled": true, "BoundOrg": "your-org-id" }
```

JSON field names still say `Routes` for connectors (`MaxRoutes`, `CurrentUsage.Routes`). `isTrial` may appear in lowercase. Older brokers omit `Enrolled` and `BoundOrg` and publish only `{ Pending, Reason }`.

### Fields operators use

| Field | Meaning |
| - | - |
| `Tier`, `IsActive`, `Plan`, `LicensedTo` | Plan in force |
| `ExpiresUtc`, `SecondsToExpiry` | Hard expiry of the license |
| `Fingerprint`, `FingerprintSource` | Value to send Coreflux for an offline license |
| `Activation.Mode` | `online` (lease) or `offline` (signed file) |
| `Activation.BindingOk` / `BindingReason` / `TamperDetected` | Whether the broker actually honoured the license |
| `Activation.Online.LeaseExpiresUtc` / `LastValidatedUtc` / `SeatMode` | Online lease freshness (`hard` = seat pool enforced, `soft` = Enterprise cluster honor-system) |
| `EffectiveLimits`, `CurrentUsage`, `Features` | Quotas and gates |
| `Enrollment.Pending` / `Enrollment.Reason` | A problem was recorded, and the broker's sentence for it. `Pending: false` only means no problem was recorded |
| `Enrollment.Enrolled` | `true` only while this broker is bound to an organization or heartbeating with its enrollment credential. A credential file on disk alone doesn't count. This is the signal to treat enrollment as done |
| `Enrollment.BoundOrg` | Organization id when the broker has one. With `Enrolled`, this is what Coreflux HUB uses for **Enrolled** |

> [!WARNING]
>
> `Enrollment.Pending: false` does **not** mean the broker is enrolled. The broker sets `Pending` when it recorded a problem. A broker that never attempted enrollment reports the same `Pending: false` as one that finished. Treat a missing `Reason` as “no problem reported,” not as proof of an org binding. Treat enrollment as done when `Enrolled` is `true` or `BoundOrg` names the organization (Coreflux HUB shows **Enrolled**). A payload that only has `{ Pending, Reason }` does not report enrollment; HUB shows **Enrollment not reported**.

### Enrollment reasons

When `Enrollment.Pending` is `true`, `Reason` is a full sentence. Typical causes:

| Cause | What to do |
| - | - |
| No credential supplied | Set `COREFLUX_ACTIVATION_CODE`, or paste an `et_…` token in the HUB License tab / `-enroll` |
| Authority unreachable | Allow egress to `https://license.coreflux.org`; the broker retries on its own |
| Platform unreachable | Allow egress to `https://brokers.coreflux.org`; the broker keeps serving and retries |
| Seat pool full | Wait for a killed instance's lease to expire, or manage the fleet at [portal.coreflux.org](https://portal.coreflux.org) |
| Licence unclaimed | The license is not bound to an organization yet. Manage the fleet at [portal.coreflux.org](https://portal.coreflux.org) — retrying the broker will not help |
| Instance mismatch | Expected: a lease cannot move between hosts |

***

## Offline fingerprint

`--show-fingerprint` (and the `Fingerprint` field on the status payload) is what Coreflux binds an offline license to.

| `FingerprintSource` | Host | Stable across restarts? |
| - | - | - |
| `machine-id` | Linux | Yes |
| `IOPlatformUUID` | macOS | Yes |
| `MachineGuid` | Windows | Yes |
| `hostname+mac` | Containers with no readable machine id | **No** — can change when the container is recreated |

Do not request an offline license against `hostname+mac` unless you accept that recreating the container may drop the broker back to Community.

***

## Persist the data volume

The license, install identity, and enrollment credential live under `{data directory}/config/`. Official images use `CONFIG_PATH=/etc/project`.

| Path (under the data directory) | Why it must persist |
| - | - |
| `config/license.jws` | Active license or online lease |
| `config/instance-id` | Install identity — one volume is one seat. Restarts reclaim the same seat instead of spending a new one |
| `config/enrollment-token` | Drop-file for a one-shot `et_…` token (`--enroll` writes here; the broker deletes it after a successful exchange when the path is writable) |
| `config/enrollment/` | Persisted org credential after a successful enroll |

> [!WARNING]
>
> Never copy `config/instance-id` between hosts, and never bake `config/` into an image after first boot. Every broker launched from that image then claims the **same** seat. Build images before first boot, or delete `config/instance-id` and `config/enrollment/` before snapshotting.

Online-activated brokers with `COREFLUX_ACTIVATION_CODE` and an **empty** volume mint a new install identity and consume a new seat. Restoring the old volume is cheaper than re-activating. If the volume is gone, manage the fleet at [portal.coreflux.org](https://portal.coreflux.org) before activating on a new volume.

Enrolled brokers need `config/enrollment/` on the same volume. An enrollment token is single-use: if the credential is on an emptyDir and the pod restarts, the next exchange fails and will not self-heal.

```yaml wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
volumeMounts:
  - name: broker-data
    mountPath: /etc/project
volumes:
  - name: broker-data
    persistentVolumeClaim:
      claimName: coreflux-data
```

```bash wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
docker run --pull=always -d --name coreflux_broker \
  -p 1883:1883 -p 5000:5000 -p 9100:9100 \
  -e COREFLUX_ACTIVATION_CODE=CFLX-XXXX-XXXX-XXXX \
  -v project-volume:/etc/project \
  coreflux/coreflux-mqtt-broker:latest
```

***

## Error messages

| Situation | Typical message |
| - | - |
| Artifact budget full | `Artifact budget exceeded. Max N artifact(s) allowed on this tier.` |
| Connector limit reached | `Tier limit exceeded: Maximum allowed routes are N.` |
| Advanced connector, wrong tier | `Route type 'X' requires a Growth or Enterprise license.` |
| RBAC rule, wrong tier | `RBAC / Topic Access Control rules require a Growth or Enterprise license.` |
| Bad signed file | `Signed license failed verification (bad signature, wrong product, or not yet valid).` |
| Not a JWS and not a file | `Not a signed license file (expected a compact JWS).` |

***

## Best practices

> **Prefer an activation code when the broker can reach the network**
>
> Online activation refreshes the lease, picks up plan changes, and releases the seat on a graceful shutdown. Get a code (including a 30-day Growth-type license) at [portal.coreflux.org](https://portal.coreflux.org). Keep `COREFLUX_ACTIVATION_CODE` in the process environment (or activate once with `-activateLicense` and persist `config/license.jws`).

> **Use a signed file only when the host is air-gapped**
>
> Offline licenses are hardware-bound. Collect `--show-fingerprint` from the real host — not from a laptop you will not deploy.

> **Keep config/ on the same volume across upgrades**
>
> Replacing the image while keeping `/etc/project` (or `/var/lib/coreflux`) preserves the license, the seat, and enrollment.

> **Do not publish the ops port**
>
> `GET /license` on the [ops listener](/latest/mqtt-broker/operational-endpoints#license-status) is unauthenticated. Bind ops to localhost or a private network. The same status is on `$SYS/Coreflux/License` for MQTT clients that already authenticate.

> [!WARNING]
>
> Losing connectivity never bricks a licensed broker. The signed license is checked locally. An online lease keeps running until its expiry plus grace; if refresh later sees a revocation, the broker reverts to Community.

***

## Next Steps

> **[License tab in Coreflux HUB](/hub/system/configuration#license)**
>
> Activate with a code or signed file, refresh a lease, and enroll from System Config.

> **[Broker Commands](/latest/mqtt-broker/commands#license)**
>
> Publish `-activateLicense`, `-loadLicense`, `-refreshLicense`, and `-enroll` over MQTT.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.