diff --git a/docs/diagrams/activation-flow.svg b/docs/diagrams/activation-flow.svg
new file mode 100644
index 0000000..d1adc2f
--- /dev/null
+++ b/docs/diagrams/activation-flow.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/diagrams/enrollment-protocol.svg b/docs/diagrams/enrollment-protocol.svg
new file mode 100644
index 0000000..4a8df37
--- /dev/null
+++ b/docs/diagrams/enrollment-protocol.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/diagrams/model-a-activation.svg b/docs/diagrams/model-a-activation.svg
new file mode 100644
index 0000000..c02f33d
--- /dev/null
+++ b/docs/diagrams/model-a-activation.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/diagrams/model-b-activation.svg b/docs/diagrams/model-b-activation.svg
new file mode 100644
index 0000000..81f2515
--- /dev/null
+++ b/docs/diagrams/model-b-activation.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/diagrams/stage0-enrollment.svg b/docs/diagrams/stage0-enrollment.svg
new file mode 100644
index 0000000..487485a
--- /dev/null
+++ b/docs/diagrams/stage0-enrollment.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/enrollment-and-activation.md b/docs/enrollment-and-activation.md
index d92dd2b..f877ce2 100644
--- a/docs/enrollment-and-activation.md
+++ b/docs/enrollment-and-activation.md
@@ -39,6 +39,10 @@ Mosquitto does **not** require passwords: with `allow_anonymous true` on a dedic
Only the backend may subscribe to `enroll/request/+`. Devices cannot publish to response topics.
+
+
+Mermaid source of this diagram
+
```mermaid
sequenceDiagram
participant B as Board
@@ -57,6 +61,8 @@ sequenceDiagram
B->>M: reconnect as FN / pw
```
+
+
- `sig` = Ed25519 signature by the backend over `S`, `B`, `n1`, and the Client ID. It stops a man in the middle from substituting their own key.
- The password is never transmitted. First successful FN login is the enrollment acknowledgement.
- Plaintext passwords are never stored; Dynamic Security keeps a hash, so re-issue means rotate.
@@ -88,6 +94,10 @@ The database is authoritative for ownership. A successful broker command alone d
The board's credential is created once at enrollment and never changes. Activation only changes which roles the FN client holds.
+
+
+Mermaid source of this diagram
+
```mermaid
sequenceDiagram
participant O as Operator
@@ -103,6 +113,8 @@ sequenceDiagram
B->>M: use device/[SN]/... topics
```
+
+
- **Roles:** one assignment role per machine, `machine-`, with **literal** topics such as `device/SN000123/sales/report`. `%u` cannot express the SN here because the username is the FN. Plus shared capability roles (`vending`, `news`, `updates`).
- **Backend** subscribes with wildcards (`device/+/...`), takes the SN from the topic, and checks in the database that this SN is assigned to the publishing board.
- **Replacing a board for SN000123:** disable and kick `FN-old`, remove its roles; the new board enrolls as a new FN; activation attaches `machine-SN000123` to the new FN. The role's ACL text is unchanged; only which client holds it changes.
@@ -112,6 +124,10 @@ sequenceDiagram
At activation the board gets a second, machine-level broker identity. The same X25519 exchange is reused.
+
+
+Mermaid source of this diagram
+
```mermaid
sequenceDiagram
participant O as Operator
@@ -130,6 +146,8 @@ sequenceDiagram
G->>M: disable FN client (or keep for rescue / re-enrollment)
```
+
+
- **One shared role** `vending-device` with `device/%u/...`, because the username equals the SN in the topic.
- Use a **fresh** keypair on the board at each activation, not the enrollment one.
- **Bind the SN client's Client ID** to the current board (for example its FN) with `setClientId`, if the deployed version supports it. A copied SN password is then useless from any other device, and the binding is readable with `getClient`.
diff --git a/docs/sn-as-username-process.md b/docs/sn-as-username-process.md
index e6c70ad..91e8922 100644
--- a/docs/sn-as-username-process.md
+++ b/docs/sn-as-username-process.md
@@ -111,6 +111,10 @@ Role `enroll` (assigned to the anonymous group):
### 7.2 Protocol
+
+
+Mermaid source of this diagram
+
```mermaid
sequenceDiagram
participant B as Board
@@ -128,6 +132,8 @@ sequenceDiagram
B->>B: persist FN and pw to flash, then reconnect as FN
```
+
+
- `sig` = Ed25519 over `S || B || n1 || clientid || FN`. Binding the FN and the Client ID means a reply for another request, board or identity does not verify.
- The password is **hex of HKDF-SHA256(shared secret, salt = n1, info = "robot-market/mqtt-pw/v1|" + FN, 32 bytes)**. The label separates this use of the secret from any other.
- The first successful FN login is the enrollment acknowledgement.
@@ -155,6 +161,10 @@ The board logs in as `FN`, Client ID `FN`, with the derived password, sends `boa
### 9.2 Flow
+
+
+Mermaid source of this diagram
+
```mermaid
sequenceDiagram
participant O as Operator (UI)
@@ -175,6 +185,8 @@ sequenceDiagram
G->>G: DB: ACTIVE, disable the FN client, audit
```
+
+
### 9.3 Rules that make it safe
1. **SAS bound to the activation key.** The board shows a code derived from `B2` (and `n2`, FN). The operator compares it with what the backend received. An attacker who stole an FN password and sends a request with their own key produces a code that does not match what the real board displays. **This check is mandatory**, not optional; without it the operator could attach a stranger's FN to a real SN.
2. **Activation code** (from the existing activation flow): single use, expiring, bound to one SN, attempt-limited. It proves the operator is physically at the machine.