Fix Mermaid parse errors in the design docs

Semicolons end a statement in Mermaid sequence diagrams and angle brackets
are treated as HTML, so messages like "shared = X25519(s, B); pw = ..." and
"enroll/request/<cid>" broke rendering. Use commas and {cid} style
placeholders instead.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 10:39:12 +03:30
co-authored by Claude Sonnet 5.5
parent 6c2fd0648f
commit 5b7a2c5584
2 changed files with 23 additions and 23 deletions
+12 -12
View File
@@ -46,13 +46,13 @@ sequenceDiagram
participant G as Go backend participant G as Go backend
B->>B: random Client ID, X25519 keypair (b, B), nonce n1 B->>B: random Client ID, X25519 keypair (b, B), nonce n1
B->>M: CONNECT (TLS, anonymous, clientId=random) B->>M: CONNECT (TLS, anonymous, clientId=random)
B->>G: enroll/request/<cid> {B, n1, mac} B->>G: enroll/request/{cid} {B, n1, mac}
G->>G: create FN record, ephemeral (s, S) G->>G: create FN record, ephemeral (s, S)
G->>G: shared = X25519(s, B); pw = HKDF(shared, FN, n1) G->>G: shared = X25519(s, B), pw = HKDF(shared, FN, n1)
G->>M: Dynamic Security: create client FN, pw, role board-bootstrap G->>M: Dynamic Security: create client FN, pw, role board-bootstrap
G->>B: enroll/response/<cid> {FN, S, sig} (not retained) G->>B: enroll/response/{cid} {FN, S, sig} (not retained)
B->>B: verify sig with pinned public key B->>B: verify sig with pinned public key
B->>B: shared = X25519(b, S); same pw B->>B: shared = X25519(b, S), same pw
B->>B: persist FN + pw to flash B->>B: persist FN + pw to flash
B->>M: reconnect as FN / pw B->>M: reconnect as FN / pw
``` ```
@@ -94,13 +94,13 @@ sequenceDiagram
participant G as Go backend participant G as Go backend
participant M as Mosquitto participant M as Mosquitto
participant B as Board (FN) participant B as Board (FN)
B->>G: board/<FN>/activation/request B->>G: board/{FN}/activation/request
O->>G: pick SN, confirm code and short string O->>G: pick SN, confirm code and short string
G->>M: ensure role machine-<SN> (literal ACLs device/<SN>/...) G->>M: ensure role machine-{SN} (literal ACLs device/{SN}/...)
G->>M: add roles machine-<SN> + capability roles to client FN G->>M: add roles machine-{SN} + capability roles to client FN
G->>B: board/<FN>/activation/response {SN, sig} G->>B: board/{FN}/activation/response {SN, sig}
B->>B: store SN, reconnect as FN B->>B: store SN, reconnect as FN
B->>M: use device/<SN>/... topics B->>M: use device/{SN}/... topics
``` ```
- **Roles:** one assignment role per machine, `machine-<SN>`, 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`). - **Roles:** one assignment role per machine, `machine-<SN>`, 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`).
@@ -119,12 +119,12 @@ sequenceDiagram
participant M as Mosquitto participant M as Mosquitto
participant B as Board (FN) participant B as Board (FN)
B->>B: new ephemeral X25519 keypair (b2, B2) B->>B: new ephemeral X25519 keypair (b2, B2)
B->>G: board/<FN>/activation/request {B2, n2} B->>G: board/{FN}/activation/request {B2, n2}
O->>G: pick SN, confirm code and short string O->>G: pick SN, confirm code and short string
G->>G: ephemeral (s2, S2); shared = X25519(s2, B2) G->>G: ephemeral (s2, S2), shared = X25519(s2, B2)
G->>G: pw = HKDF(shared, SN, n2, generation) G->>G: pw = HKDF(shared, SN, n2, generation)
G->>M: create or update client SN: pw, clientId bound to board, role vending-device G->>M: create or update client SN: pw, clientId bound to board, role vending-device
G->>B: board/<FN>/activation/response {SN, S2, sig} G->>B: board/{FN}/activation/response {SN, S2, sig}
B->>B: verify sig, derive same pw, store SN + pw B->>B: verify sig, derive same pw, store SN + pw
B->>M: reconnect as SN / pw B->>M: reconnect as SN / pw
G->>M: disable FN client (or keep for rescue / re-enrollment) G->>M: disable FN client (or keep for rescue / re-enrollment)
+11 -11
View File
@@ -118,13 +118,13 @@ sequenceDiagram
participant G as Go backend participant G as Go backend
B->>B: random Client ID, X25519 pair (b, B), nonce n1 B->>B: random Client ID, X25519 pair (b, B), nonce n1
B->>M: CONNECT anonymous, clientId=random (TLS) B->>M: CONNECT anonymous, clientId=random (TLS)
B->>M: SUBSCRIBE enroll/response/<cid> (own topic only) B->>M: SUBSCRIBE enroll/response/{cid} (own topic only)
B->>G: enroll/request/<cid> {B, n1, mac} B->>G: enroll/request/{cid} {B, n1, mac}
G->>G: reserve <cid>, assign FN, ephemeral (s, S) G->>G: reserve {cid}, assign FN, ephemeral (s, S)
G->>G: shared = X25519(s, B); pw = HKDF(shared, salt=n1, info=label|FN) G->>G: shared = X25519(s, B), pw = HKDF(shared, salt=n1, info=label|FN)
G->>M: dynsec createClient FN, pw, clientid=FN, role board-bootstrap G->>M: dynsec createClient FN, pw, clientid=FN, role board-bootstrap
G->>B: enroll/response/<cid> {FN, S, sig} (not retained) G->>B: enroll/response/{cid} {FN, S, sig} (not retained)
B->>B: verify sig; shared = X25519(b, S); same pw B->>B: verify sig, shared = X25519(b, S), same pw
B->>B: persist FN + pw to flash, then reconnect as FN B->>B: persist FN + pw to flash, then reconnect as FN
``` ```
@@ -162,17 +162,17 @@ sequenceDiagram
participant M as Mosquitto participant M as Mosquitto
participant B as Board (FN session) participant B as Board (FN session)
B->>B: fresh X25519 pair (b2, B2), nonce n2, SAS = digits(hash(B2 || n2 || FN)) B->>B: fresh X25519 pair (b2, B2), nonce n2, SAS = digits(hash(B2 || n2 || FN))
B->>G: board/<FN>/activation/request {B2, n2} B->>G: board/{FN}/activation/request {B2, n2}
G->>O: pending request FN, MAC label, SAS, time G->>O: pending request FN, MAC label, SAS, time
O->>G: choose SN, enter activation code, confirm SAS matches the board O->>G: choose SN, enter activation code, confirm SAS matches the board
G->>G: DB: ACTIVATING (FN, SN, generation g+1), unique constraint G->>G: DB: ACTIVATING (FN, SN, generation g+1), unique constraint
G->>G: ephemeral (s2, S2); shared2; pw_sn = HKDF(shared2, salt=n2, info=label|SN|g+1) G->>G: ephemeral (s2, S2), shared2, pw_sn = HKDF(shared2, salt=n2, info=label|SN|g+1)
G->>M: dynsec create or update client SN: pw_sn, role vending-device, clientid = FN G->>M: dynsec create or update client SN: pw_sn, role vending-device, clientid = FN
G->>B: board/<FN>/activation/response {SN, g+1, S2, sig} G->>B: board/{FN}/activation/response {SN, g+1, S2, sig}
B->>B: verify sig, derive pw_sn, persist SN + pw_sn + generation, reconnect B->>B: verify sig, derive pw_sn, persist SN + pw_sn + generation, reconnect
B->>M: CONNECT username=SN, clientId=FN, password=pw_sn B->>M: CONNECT username=SN, clientId=FN, password=pw_sn
M-->>G: first message on device/<SN>/... (or presence) M-->>G: first message on device/{SN}/... (or presence)
G->>G: DB: ACTIVE; disable the FN client; audit G->>G: DB: ACTIVE, disable the FN client, audit
``` ```
### 9.3 Rules that make it safe ### 9.3 Rules that make it safe