From 371c029e8aade6127392d7dd89238ed6e11d151c Mon Sep 17 00:00:00 2001 From: Imugiii Date: Mon, 15 Jun 2026 10:11:04 +0000 Subject: [PATCH] docs(merise): replace stale v0.1 drawio with per-subdomain Mermaid + SVG (21 entities) --- docs/merise/_diagrams/mcd-catalogue.drawio | 67 ------- docs/merise/_diagrams/mcd-catalogue.mmd | 51 +++++ docs/merise/_diagrams/mcd-catalogue.svg | 5 +- docs/merise/_diagrams/mcd-commande.drawio | 93 --------- docs/merise/_diagrams/mcd-commande.svg | 4 - docs/merise/_diagrams/mcd-global.drawio | 182 ------------------ docs/merise/_diagrams/mcd-global.svg | 4 - .../_diagrams/mcd-ingredients-stock.mmd | 61 ++++++ .../_diagrams/mcd-ingredients-stock.svg | 1 + docs/merise/_diagrams/mcd-order.mmd | 67 +++++++ docs/merise/_diagrams/mcd-order.svg | 1 + docs/merise/_diagrams/mcd-rbac.drawio | 57 ------ docs/merise/_diagrams/mcd-rbac.mmd | 64 ++++++ docs/merise/_diagrams/mcd-rbac.svg | 5 +- docs/merise/_diagrams/mld-catalogue.drawio | 59 ------ docs/merise/_diagrams/mld-commande.drawio | 78 -------- docs/merise/_diagrams/mld-rbac.drawio | 56 ------ docs/merise/mcd.md | 34 +++- 18 files changed, 273 insertions(+), 616 deletions(-) delete mode 100644 docs/merise/_diagrams/mcd-catalogue.drawio create mode 100644 docs/merise/_diagrams/mcd-catalogue.mmd delete mode 100644 docs/merise/_diagrams/mcd-commande.drawio delete mode 100644 docs/merise/_diagrams/mcd-commande.svg delete mode 100644 docs/merise/_diagrams/mcd-global.drawio delete mode 100644 docs/merise/_diagrams/mcd-global.svg create mode 100644 docs/merise/_diagrams/mcd-ingredients-stock.mmd create mode 100644 docs/merise/_diagrams/mcd-ingredients-stock.svg create mode 100644 docs/merise/_diagrams/mcd-order.mmd create mode 100644 docs/merise/_diagrams/mcd-order.svg delete mode 100644 docs/merise/_diagrams/mcd-rbac.drawio create mode 100644 docs/merise/_diagrams/mcd-rbac.mmd delete mode 100644 docs/merise/_diagrams/mld-catalogue.drawio delete mode 100644 docs/merise/_diagrams/mld-commande.drawio delete mode 100644 docs/merise/_diagrams/mld-rbac.drawio diff --git a/docs/merise/_diagrams/mcd-catalogue.drawio b/docs/merise/_diagrams/mcd-catalogue.drawio deleted file mode 100644 index c9cf3e8..0000000 --- a/docs/merise/_diagrams/mcd-catalogue.drawio +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mcd-catalogue.mmd b/docs/merise/_diagrams/mcd-catalogue.mmd new file mode 100644 index 0000000..698a179 --- /dev/null +++ b/docs/merise/_diagrams/mcd-catalogue.mmd @@ -0,0 +1,51 @@ +erDiagram + category { + int id PK + varchar name + varchar slug + varchar image_path + smallint display_order + tinyint is_active + } + product { + int id PK + int category_id FK + varchar name + text description + int price_cents + smallint vat_rate + varchar image_path + tinyint is_available + smallint display_order + } + menu { + int id PK + int category_id FK + int burger_product_id FK + varchar name + text description + int price_normal_cents + int price_maxi_cents + varchar image_path + tinyint is_available + smallint display_order + } + menu_slot { + int id PK + int menu_id FK + varchar name + enum slot_type + tinyint is_required + smallint display_order + } + menu_slot_option { + int menu_slot_id FK + int product_id FK + } + + category ||--o{ product : "groups" + category ||--o{ menu : "groups" + menu ||--|| product : "anchors (burger_product_id)" + menu ||--o{ menu_slot : "defines_slot" + menu_slot ||--o{ menu_slot_option : "lists" + product ||--o{ menu_slot_option : "is_eligible_for" diff --git a/docs/merise/_diagrams/mcd-catalogue.svg b/docs/merise/_diagrams/mcd-catalogue.svg index c3a2016..38c2764 100644 --- a/docs/merise/_diagrams/mcd-catalogue.svg +++ b/docs/merise/_diagrams/mcd-catalogue.svg @@ -1,4 +1 @@ - - - -
CATEGORIE
id : INT (PK)
libelle : VARCHAR (UNIQUE)
slug : VARCHAR (UNIQUE)
image_path : VARCHAR
ordre : SMALLINT
est_actif : BOOLEAN
CATEGORIEid : INT (PK)...
PRODUIT
id : INT (PK)
categorie_id : INT (FK)
libelle : VARCHAR
description : TEXT
prix_ttc_cents : INT
image_path : VARCHAR
est_disponible : BOOLEAN
ordre : SMALLINT
PRODUITid : INT (PK)...
MENU
id : INT (PK)
categorie_id : INT (FK)
libelle : VARCHAR
description : TEXT
prix_ttc_cents : INT
image_path : VARCHAR
est_disponible : BOOLEAN
ordre : SMALLINT
MENUid : INT (PK)...
MENU_PRODUIT (associative)
menu_id : INT (PK, FK)
produit_id : INT (PK, FK)
role : ENUM
position : SMALLINT
MENU_PRODUIT (associative)menu_id : INT (PK,...
regroupe
regroupe
(0,N)
(0,N)
(1,1)
(1,1)
regroupe
regroupe
(0,N)
(0,N)
(1,1)
(1,1)
fait_partie_de
fait_partie_de
(0,N)
(0,N)
(1,1)
(1,1)
compose
compose
(1,N)
(1,N)
(1,1)
(1,1)
Text is not SVG - cannot display
\ No newline at end of file +

groups

groups

anchors (burger_product_id)

defines_slot

lists

is_eligible_for

category

int

id

PK

varchar

name

varchar

slug

varchar

image_path

smallint

display_order

tinyint

is_active

product

int

id

PK

int

category_id

FK

varchar

name

text

description

int

price_cents

smallint

vat_rate

varchar

image_path

tinyint

is_available

smallint

display_order

menu

int

id

PK

int

category_id

FK

int

burger_product_id

FK

varchar

name

text

description

int

price_normal_cents

int

price_maxi_cents

varchar

image_path

tinyint

is_available

smallint

display_order

menu_slot

int

id

PK

int

menu_id

FK

varchar

name

enum

slot_type

tinyint

is_required

smallint

display_order

menu_slot_option

int

menu_slot_id

FK

int

product_id

FK

\ No newline at end of file diff --git a/docs/merise/_diagrams/mcd-commande.drawio b/docs/merise/_diagrams/mcd-commande.drawio deleted file mode 100644 index a6ef277..0000000 --- a/docs/merise/_diagrams/mcd-commande.drawio +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mcd-commande.svg b/docs/merise/_diagrams/mcd-commande.svg deleted file mode 100644 index 2d4be3b..0000000 --- a/docs/merise/_diagrams/mcd-commande.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
COMMANDE
id : INT (PK)
numero : VARCHAR (UNIQUE)
source : ENUM (kiosk|comptoir|drive)
mode_consommation : ENUM (sur_place|a_emporter|drive)
statut : ENUM
total_ht_cents : INT
total_tva_cents : INT
total_ttc_cents : INT
tva_taux_pourmille : SMALLINT
paye_a : DATETIME
USER
id : INT (PK)
(detail dans RBAC)
COMMANDE_EVENT
id : INT (PK)
commande_id : INT (FK)
event_type : ENUM
from_statut : ENUM (NULL)
to_statut : ENUM
user_id : INT (FK, NULL)
payload : JSON (NULL)
created_at : DATETIME
LIGNE_COMMANDE
id : INT (PK)
commande_id : INT (FK)
type_item : ENUM (produit|menu)
produit_id : INT (FK, NULL)
menu_id : INT (FK, NULL)
libelle_snapshot : VARCHAR
prix_unitaire_ttc_cents_snapshot : INT
quantite : SMALLINT
PRODUIT
id : INT (PK)
(detail dans Catalogue)
MENU
id : INT (PK)
(detail dans Catalogue)
contient
(1,N)
(1,1)
refere_si_type_produit
(0,1)
(0,N)
refere_si_type_menu
(0,N)
Polymorphisme
Exactement UNE des deux references est non-nulle.
Discriminateur : type_item ∈ {produit, menu}.
Contrainte CHECK SQL au MLD.
journalise
(1,N)
(1,1)
declenche
(0,N)
(0,1)
(0,1)
Journal d'audit (event sourcing)
Append-only : aucun UPDATE / DELETE applicatif.
user_id NULL si auto-validation kiosk.
ON DELETE CASCADE cote commande_id.
ON DELETE SET NULL cote user_id.
\ No newline at end of file diff --git a/docs/merise/_diagrams/mcd-global.drawio b/docs/merise/_diagrams/mcd-global.drawio deleted file mode 100644 index 962f01b..0000000 --- a/docs/merise/_diagrams/mcd-global.drawio +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mcd-global.svg b/docs/merise/_diagrams/mcd-global.svg deleted file mode 100644 index 1d26537..0000000 --- a/docs/merise/_diagrams/mcd-global.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
CATEGORIE
PRODUIT
MENU_PRODUIT
MENU
LIGNE_COMMANDE
COMMANDE
COMMANDE_EVENT
USER
ROLE
ROLE_PERMISSION
PERMISSION
regroupe
(0,N)
(1,1)
regroupe
(0,N)
(1,1)
fait_partie_de
(0,N)
(1,1)
compose
(1,N)
(1,1)
contient
(1,N)
(1,1)
refere_si_type_produit
(0,1)
(0,N)
refere_si_type_menu
(0,1)
(0,N)
a_pour_role
(1,1)
(0,N)
possede
(0,N)
(1,1)
assignee_a
(0,N)
(1,1)
journalise
(1,N)
(1,1)
declenche
(0,N)
(0,1)
\ No newline at end of file diff --git a/docs/merise/_diagrams/mcd-ingredients-stock.mmd b/docs/merise/_diagrams/mcd-ingredients-stock.mmd new file mode 100644 index 0000000..dff0eee --- /dev/null +++ b/docs/merise/_diagrams/mcd-ingredients-stock.mmd @@ -0,0 +1,61 @@ +erDiagram + product { + int id PK + varchar name + } + ingredient { + int id PK + varchar name + varchar unit + int stock_quantity + int stock_capacity + smallint pack_size + varchar pack_label + smallint low_stock_pct + smallint critical_stock_pct + tinyint is_active + } + product_ingredient { + int product_id FK + int ingredient_id FK + smallint quantity_normal + smallint quantity_maxi + tinyint is_removable + tinyint is_addable + int extra_price_cents + } + allergen { + int id PK + varchar code + varchar name + text description + } + ingredient_allergen { + int ingredient_id FK + int allergen_id FK + } + customer_order { + int id PK + varchar order_number + } + user { + int id PK + varchar email + } + stock_movement { + int id PK + int ingredient_id FK + enum movement_type + int delta + int order_id FK + int user_id FK + varchar note + } + + product ||--o{ product_ingredient : "is_composed_of" + ingredient ||--o{ product_ingredient : "appears_in" + ingredient ||--o{ ingredient_allergen : "contains" + allergen ||--o{ ingredient_allergen : "is_present_in" + ingredient ||--o{ stock_movement : "decrements" + customer_order |o--o{ stock_movement : "triggers" + user |o--o{ stock_movement : "logs" diff --git a/docs/merise/_diagrams/mcd-ingredients-stock.svg b/docs/merise/_diagrams/mcd-ingredients-stock.svg new file mode 100644 index 0000000..615a975 --- /dev/null +++ b/docs/merise/_diagrams/mcd-ingredients-stock.svg @@ -0,0 +1 @@ +

is_composed_of

appears_in

contains

is_present_in

decrements

triggers

logs

product

int

id

PK

varchar

name

ingredient

int

id

PK

varchar

name

varchar

unit

int

stock_quantity

int

stock_capacity

smallint

pack_size

varchar

pack_label

smallint

low_stock_pct

smallint

critical_stock_pct

tinyint

is_active

product_ingredient

int

product_id

FK

int

ingredient_id

FK

smallint

quantity_normal

smallint

quantity_maxi

tinyint

is_removable

tinyint

is_addable

int

extra_price_cents

allergen

int

id

PK

varchar

code

varchar

name

text

description

ingredient_allergen

int

ingredient_id

FK

int

allergen_id

FK

customer_order

int

id

PK

varchar

order_number

user

int

id

PK

varchar

email

stock_movement

int

id

PK

int

ingredient_id

FK

enum

movement_type

int

delta

int

order_id

FK

int

user_id

FK

varchar

note

\ No newline at end of file diff --git a/docs/merise/_diagrams/mcd-order.mmd b/docs/merise/_diagrams/mcd-order.mmd new file mode 100644 index 0000000..be06a07 --- /dev/null +++ b/docs/merise/_diagrams/mcd-order.mmd @@ -0,0 +1,67 @@ +erDiagram + customer_order { + int id PK + varchar order_number + varchar idempotency_key + enum source + int acting_user_id FK + enum service_mode + enum status + int total_ht_cents + int total_vat_cents + int total_ttc_cents + datetime paid_at + datetime delivered_at + datetime cancelled_at + } + order_item { + int id PK + int order_id FK + enum item_type + int product_id FK + int menu_id FK + enum format + varchar label_snapshot + int unit_price_cents_snapshot + smallint vat_rate_snapshot + smallint quantity + } + order_item_selection { + int id PK + int order_item_id FK + int menu_slot_id FK + int product_id FK + varchar label_snapshot + } + order_item_modifier { + int id PK + int order_item_id FK + int ingredient_id FK + enum action + int extra_price_cents + } + product { + int id PK + varchar name + } + menu { + int id PK + varchar name + } + menu_slot { + int id PK + varchar name + } + ingredient { + int id PK + varchar name + } + + customer_order ||--o{ order_item : "contains" + order_item }o--o| product : "references_product" + order_item }o--o| menu : "references_menu" + order_item ||--o{ order_item_selection : "fills_slot" + order_item ||--o{ order_item_modifier : "modifies_ingredient" + menu_slot ||--o{ order_item_selection : "slot_filled_by" + product ||--o{ order_item_selection : "chosen_for_slot" + ingredient ||--o{ order_item_modifier : "modified_by" diff --git a/docs/merise/_diagrams/mcd-order.svg b/docs/merise/_diagrams/mcd-order.svg new file mode 100644 index 0000000..aeb5ac7 --- /dev/null +++ b/docs/merise/_diagrams/mcd-order.svg @@ -0,0 +1 @@ +

contains

references_product

references_menu

fills_slot

modifies_ingredient

slot_filled_by

chosen_for_slot

modified_by

customer_order

int

id

PK

varchar

order_number

varchar

idempotency_key

enum

source

int

acting_user_id

FK

enum

service_mode

enum

status

int

total_ht_cents

int

total_vat_cents

int

total_ttc_cents

datetime

paid_at

datetime

delivered_at

datetime

cancelled_at

order_item

int

id

PK

int

order_id

FK

enum

item_type

int

product_id

FK

int

menu_id

FK

enum

format

varchar

label_snapshot

int

unit_price_cents_snapshot

smallint

vat_rate_snapshot

smallint

quantity

order_item_selection

int

id

PK

int

order_item_id

FK

int

menu_slot_id

FK

int

product_id

FK

varchar

label_snapshot

order_item_modifier

int

id

PK

int

order_item_id

FK

int

ingredient_id

FK

enum

action

int

extra_price_cents

product

int

id

PK

varchar

name

menu

int

id

PK

varchar

name

menu_slot

int

id

PK

varchar

name

ingredient

int

id

PK

varchar

name

\ No newline at end of file diff --git a/docs/merise/_diagrams/mcd-rbac.drawio b/docs/merise/_diagrams/mcd-rbac.drawio deleted file mode 100644 index 31e109d..0000000 --- a/docs/merise/_diagrams/mcd-rbac.drawio +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mcd-rbac.mmd b/docs/merise/_diagrams/mcd-rbac.mmd new file mode 100644 index 0000000..f3bb49a --- /dev/null +++ b/docs/merise/_diagrams/mcd-rbac.mmd @@ -0,0 +1,64 @@ +erDiagram + user { + int id PK + varchar email + varchar password_hash + varchar pin_hash + varchar first_name + varchar last_name + int role_id FK + tinyint is_active + datetime last_login_at + smallint failed_login_attempts + datetime lockout_until + datetime anonymized_at + } + role { + int id PK + varchar code + varchar label + text description + varchar default_route + enum order_source + tinyint is_active + } + role_visible_source { + int role_id FK + enum source + } + permission { + int id PK + varchar code + varchar label + text description + } + role_permission { + int role_id FK + int permission_id FK + } + audit_log { + int id PK + int actor_user_id FK + int actor_role_id FK + varchar action_code + varchar entity_type + int entity_id + varchar summary + json details + datetime created_at + } + login_throttle { + int id PK + varchar ip_address UK + smallint failed_attempts + datetime window_started_at + datetime lockout_until + datetime last_attempt_at + } + + user }o--|| role : "holds" + role ||--o{ role_visible_source : "sees_source" + role ||--o{ role_permission : "grants" + permission ||--o{ role_permission : "granted_to" + user |o--o{ audit_log : "performs" + role |o--o{ audit_log : "context_of" diff --git a/docs/merise/_diagrams/mcd-rbac.svg b/docs/merise/_diagrams/mcd-rbac.svg index e92d624..688b27f 100644 --- a/docs/merise/_diagrams/mcd-rbac.svg +++ b/docs/merise/_diagrams/mcd-rbac.svg @@ -1,4 +1 @@ - - - -
USER
id : INT (PK)
email : VARCHAR (UNIQUE, RFC 5321)
password_hash : VARCHAR (argon2id)
nom : VARCHAR
prenom : VARCHAR
role_id : INT (FK)
est_actif : BOOLEAN
last_login_at : DATETIME
ROLE
id : INT (PK)
code : VARCHAR (UNIQUE)
libelle : VARCHAR
description : TEXT
est_actif : BOOLEAN
PERMISSION
id : INT (PK)
code : VARCHAR (UNIQUE, resource.action)
libelle : VARCHAR
description : TEXT
ROLE_PERMISSION (associative)
role_id : INT (PK, FK)
permission_id : INT (PK, FK)
a_pour_role
(1,1)
(0,N)
possede
(0,N)
(1,1)
assignee_a
(0,N)
(1,1)
\ No newline at end of file +

holds

sees_source

grants

granted_to

performs

context_of

user

int

id

PK

varchar

email

varchar

password_hash

varchar

pin_hash

varchar

first_name

varchar

last_name

int

role_id

FK

tinyint

is_active

datetime

last_login_at

smallint

failed_login_attempts

datetime

lockout_until

datetime

anonymized_at

role

int

id

PK

varchar

code

varchar

label

text

description

varchar

default_route

enum

order_source

tinyint

is_active

role_visible_source

int

role_id

FK

enum

source

permission

int

id

PK

varchar

code

varchar

label

text

description

role_permission

int

role_id

FK

int

permission_id

FK

audit_log

int

id

PK

int

actor_user_id

FK

int

actor_role_id

FK

varchar

action_code

varchar

entity_type

int

entity_id

varchar

summary

json

details

datetime

created_at

login_throttle

int

id

PK

varchar

ip_address

UK

smallint

failed_attempts

datetime

window_started_at

datetime

lockout_until

datetime

last_attempt_at

\ No newline at end of file diff --git a/docs/merise/_diagrams/mld-catalogue.drawio b/docs/merise/_diagrams/mld-catalogue.drawio deleted file mode 100644 index e292dbc..0000000 --- a/docs/merise/_diagrams/mld-catalogue.drawio +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mld-commande.drawio b/docs/merise/_diagrams/mld-commande.drawio deleted file mode 100644 index 1a47a5d..0000000 --- a/docs/merise/_diagrams/mld-commande.drawio +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mld-rbac.drawio b/docs/merise/_diagrams/mld-rbac.drawio deleted file mode 100644 index 0922801..0000000 --- a/docs/merise/_diagrams/mld-rbac.drawio +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/mcd.md b/docs/merise/mcd.md index 64a889c..e910e23 100644 --- a/docs/merise/mcd.md +++ b/docs/merise/mcd.md @@ -83,8 +83,9 @@ Merise practice for models of this size. **Note on the absence of a global diagram**: a single 21-entity ER diagram would be unreadable and unmaintainable. The sub-domain decomposition below is the intentional -structural choice. The `.drawio` source files will be regenerated from this document as the -single reference once the MCD is stabilised (regeneration tracked in `docs/notes/`). +structural choice. Each sub-domain is a Mermaid `erDiagram` (authoritative, rendered +natively) with a portable SVG render in `docs/merise/_diagrams/`; see section 11 for the +sources and regeneration command. --- @@ -600,10 +601,27 @@ audit writes, reset/lockout, anonymisation). The treatment-layer additions are t --- -## 11. Note on .drawio diagram regeneration +## 11. Diagram sources and regeneration -The `.drawio` XML sources in `docs/merise/_diagrams/` reflect the v0.1 model (11 entities, -French naming). They are scheduled for regeneration from this v0.2 MCD as a separate task. -Until regenerated, this Markdown document is the authoritative conceptual model. The Mermaid -`erDiagram` blocks in sections 4-7 render natively on GitHub and serve as the interim -graphical reference. +The authoritative graphical model is the set of Mermaid `erDiagram` blocks in sections 4-7, +one per sub-domain. They render natively on Forgejo and GitHub. The MCD is decomposed by +sub-domain on purpose: a single 21-entity diagram cannot be laid out without crossing +relationship lines (intrinsic planarity limit, and `erDiagram` offers no manual layout +control). Each sub-domain stays at 5-8 entities, which auto-layout handles cleanly. The +integrated view across sub-domains is the cross-validation table in section 8. + +Portable SVG renders live in `docs/merise/_diagrams/` (for PDF export / offline viewing): + +| Sub-domain | Source | Render | +|---|---|---| +| Catalogue | `mcd-catalogue.mmd` | `mcd-catalogue.svg` | +| Ingredients & Stock | `mcd-ingredients-stock.mmd` | `mcd-ingredients-stock.svg` | +| Order | `mcd-order.mmd` | `mcd-order.svg` | +| RBAC | `mcd-rbac.mmd` | `mcd-rbac.svg` | + +The `.mmd` files are extracted from the `erDiagram` blocks above; the `.svg` are produced by +`make docs-render` (mmdc). If a block here changes, re-extract the matching `.mmd` and re-run +`make docs-render`. The legacy v0.1 `.drawio` sources have been removed: drawio gave manual +layout control but required hand-editing and did not render in the Markdown previews, whereas +the decomposed Mermaid blocks are version-controlled, render everywhere, and stay in sync with +this document.