From 57bab0185585eeb0a0979a1bb6a56f218cfcc02d Mon Sep 17 00:00:00 2001 From: Gronod Date: Sun, 17 May 2026 18:26:19 +0100 Subject: [PATCH] fix: repair Mermaid diagrams in ARCHITECTURE.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace \n in stateDiagram transition labels, sequenceDiagram notes, and graph edge labels — these are not valid in those contexts and cause diagrams to fail to render. Also replace Unicode × and → with plain ASCII equivalents to avoid parser issues. --- docs/ARCHITECTURE.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index fdd1c6f..6a0f7c0 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -941,8 +941,8 @@ graph TB sonarr_r --> sonarr radarr_r --> radarr - appjs -->|POST /login\nGET /me\nGET /csrf\nPOST /logout| auth - appjs -->|GET /stream SSE\nGET /user-downloads\nGET /status| dashboard + appjs -->|POST /login, GET /me, GET /csrf, POST /logout| auth + appjs -->|GET /stream SSE, GET /user-downloads, GET /status| dashboard es -->|serve static| html ``` @@ -976,16 +976,16 @@ sequenceDiagram Note over Browser,Emby: Login User->>Browser: Enter credentials (+ rememberMe) Browser->>Auth: POST /api/auth/login - Note right of Auth: Rate limit: max 10 failed\nattempts per IP / 15 min - Auth->>Emby: POST /Users/authenticatebyname\nDeviceId = sha256(username)[0:16] + Note right of Auth: Rate limit: max 10 failed attempts per IP / 15 min + Auth->>Emby: POST /Users/authenticatebyname (DeviceId = sha256(username)[0:16]) alt Valid credentials Emby-->>Auth: { User.Id, AccessToken } Auth->>Emby: GET /Users/{id} Emby-->>Auth: { Name, Policy.IsAdministrator } Auth->>Tokens: storeToken(userId, AccessToken) - Note right of Tokens: Server-side only\n31-day TTL, atomic write - Auth->>Auth: Set emby_user cookie\nhttpOnly, sameSite=strict\nsecure (if TRUST_PROXY)\nrememberMe → Max-Age 30d - Auth->>Auth: Set csrf_token cookie\nhttpOnly=false, sameSite=strict + Note right of Tokens: Server-side only, 31-day TTL, atomic write + Auth->>Auth: Set emby_user cookie (httpOnly, sameSite=strict, secure if TRUST_PROXY) + Auth->>Auth: Set csrf_token cookie (httpOnly=false, sameSite=strict) Auth-->>Browser: { success: true, user, csrfToken } Browser->>Browser: showDashboard() + startSSE() else Invalid credentials @@ -1023,7 +1023,7 @@ sequenceDiagram User->>Browser: Login success / valid session Browser->>Dashboard: GET /api/dashboard/stream (EventSource) Dashboard->>Dashboard: requireAuth: extract user/isAdmin - Dashboard->>Dashboard: Set Content-Type: text/event-stream\nRegister in activeClients + Dashboard->>Dashboard: Set Content-Type: text/event-stream, register in activeClients opt Polling disabled AND cache empty Dashboard->>Poller: pollAllServices() @@ -1033,7 +1033,7 @@ sequenceDiagram end Dashboard->>Cache: get all poll:* keys - Dashboard->>Dashboard: Build maps, match downloads\nextractUserTag / buildTagBadges + Dashboard->>Dashboard: Build maps, match downloads, extractUserTag / buildTagBadges Dashboard-->>Browser: data: { user, isAdmin, downloads } Browser->>Browser: hideLoading() + renderDownloads() @@ -1050,7 +1050,7 @@ sequenceDiagram User->>Browser: Close tab / logout Browser->>Dashboard: TCP close (req close event) - Dashboard->>Dashboard: offPollComplete(cb)\nclearInterval(heartbeat)\ndelete activeClients[key] + Dashboard->>Dashboard: offPollComplete(cb), clearInterval(heartbeat), delete activeClients[key] ``` ### 13.4 Background Polling Cycle @@ -1094,8 +1094,8 @@ sequenceDiagram Poller->>QBT: getTorrents() QBT-->>Poller: [{ name, progress, ... }] - Poller->>Poller: Record per-task timings\nlastPollTimings = { totalMs, timestamp, tasks } - Poller->>Cache: set poll:* keys (TTL = POLL_INTERVAL × 3) + Poller->>Poller: Record per-task timings: lastPollTimings = { totalMs, timestamp, tasks } + Poller->>Cache: set poll:* keys (TTL = POLL_INTERVAL x 3) Poller->>Poller: Notify SSE subscribers (forEach cb()) Poller->>Poller: polling = false ``` @@ -1330,11 +1330,11 @@ stateDiagram-v2 Submitting --> [*] : Auth success } - LoginForm --> Dashboard : Auth success\n(fade transition) + LoginForm --> Dashboard : Auth success (fade transition) state Dashboard { [*] --> Rendering - Rendering --> Rendering : SSE message → renderDownloads() + Rendering --> Rendering : SSE message triggers renderDownloads() Rendering --> Rendering : Theme change state SSEConnection { @@ -1368,13 +1368,13 @@ stateDiagram-v2 state Disabled { [*] --> OnDemand - OnDemand : No background timer.\nData fetched when dashboard\nrequest finds empty cache. + OnDemand : No background timer. Data fetched when dashboard request finds empty cache. } Disabled --> Polling : dashboard triggers pollAllServices() Polling --> Disabled : Poll complete (on-demand) - Idle --> Polling : setInterval fires\nor immediate first poll + Idle --> Polling : setInterval fires or immediate first poll state Polling { [*] --> Locked @@ -1382,7 +1382,7 @@ stateDiagram-v2 Locked --> Fetching Fetching --> Storing : All promises resolved Fetching --> HandleError : Per-service error (caught) - Storing --> Notifying : Cache updated\nTTL = POLL_INTERVAL × 3 + Storing --> Notifying : Cache updated, TTL = POLL_INTERVAL x 3 Notifying : Notify SSE subscribers Notifying --> Done Done : polling = false @@ -1401,7 +1401,7 @@ stateDiagram-v2 [*] --> Skip Skip : polling === true, skip cycle } - Idle --> ConcurrentSkip : Interval fires while\nprevious still running + Idle --> ConcurrentSkip : Interval fires while previous still running ConcurrentSkip --> Idle : Log skip ```