- New diagrams.

This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-11-24 14:37:32 -03:00
parent 6d18019894
commit bbd3ebb279
2 changed files with 429 additions and 0 deletions

View file

@ -0,0 +1,205 @@
<svg width="800" height="600" viewBox="0 0 800 600" xmlns="http://www.w3.org/2000/svg">
<!-- Define gradients and effects -->
<defs>
<!-- Gradients for different layers -->
<linearGradient id="clientGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#667eea;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#764ba2;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="gatewayGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#06ffa5;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#00d2ff;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="authGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#f093fb;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#f5576c;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="businessGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#4facfe;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#00f2fe;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="adminGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#fa709a;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#fee140;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="serviceGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#30cfd0;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#330867;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="dbGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#43e97b;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#38f9d7;stop-opacity:0.3" />
</linearGradient>
<!-- Arrow marker -->
<marker id="arrow" markerWidth="12" markerHeight="12" refX="11" refY="6" orient="auto">
<path d="M 0 0 L 12 6 L 0 12 L 3 6 Z" fill="#4a5568" opacity="0.7"/>
</marker>
<!-- Drop shadow filter -->
<filter id="shadow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="2"/>
<feOffset dx="0" dy="2" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.15"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Background -->
<rect x="0" y="0" width="800" height="600" fill="#fafafa"/>
<!-- Title -->
<rect x="250" y="10" width="300" height="35" fill="rgba(99, 102, 241, 0.05)" rx="8"/>
<text x="400" y="33" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="20" font-weight="600" fill="#1e293b">
BotServer API Architecture
</text>
<!-- Client Applications Layer -->
<rect x="250" y="60" width="300" height="50" fill="url(#clientGrad)" stroke="#667eea" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="400" y="90" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
Client Applications
</text>
<!-- Arrow down -->
<path d="M 400 110 L 400 130" stroke="#4a5568" stroke-width="2.5" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<!-- HTTP/HTTPS Layer -->
<rect x="300" y="130" width="200" height="45" fill="rgba(99, 102, 241, 0.08)" stroke="#8b5cf6" stroke-width="1.5" rx="6" filter="url(#shadow)"/>
<text x="400" y="150" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="500" fill="#1e293b">
HTTP/HTTPS
</text>
<text x="400" y="165" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#475569">
Port 8080
</text>
<!-- Arrow down -->
<path d="M 400 175 L 400 195" stroke="#4a5568" stroke-width="2.5" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<!-- API Gateway -->
<rect x="250" y="195" width="300" height="50" fill="url(#gatewayGrad)" stroke="#00d2ff" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="400" y="220" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
API Gateway
</text>
<text x="400" y="235" text-anchor="middle" font-family="system-ui, monospace" font-size="11" fill="#475569">
/api/*
</text>
<!-- Arrows to endpoint groups -->
<path d="M 400 245 L 400 260 L 180 260 L 180 280" stroke="#4a5568" stroke-width="2" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<path d="M 400 245 L 400 280" stroke="#4a5568" stroke-width="2" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<path d="M 400 245 L 400 260 L 620 260 L 620 280" stroke="#4a5568" stroke-width="2" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<!-- Auth Endpoints -->
<rect x="80" y="280" width="200" height="80" fill="url(#authGrad)" stroke="#f5576c" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="180" y="305" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#1e293b">
Auth Endpoints
</text>
<text x="180" y="325" text-anchor="middle" font-family="system-ui, monospace" font-size="10" fill="#475569">
/auth/login
</text>
<text x="180" y="340" text-anchor="middle" font-family="system-ui, monospace" font-size="10" fill="#475569">
/auth/logout
</text>
<text x="180" y="355" text-anchor="middle" font-family="system-ui, monospace" font-size="10" fill="#475569">
/auth/token
</text>
<!-- Business Endpoints -->
<rect x="300" y="280" width="200" height="80" fill="url(#businessGrad)" stroke="#00f2fe" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="400" y="305" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#1e293b">
Business Endpoints
</text>
<text x="400" y="325" text-anchor="middle" font-family="system-ui, monospace" font-size="10" fill="#475569">
/files/* • /users/*
</text>
<text x="400" y="340" text-anchor="middle" font-family="system-ui, monospace" font-size="10" fill="#475569">
/groups/* • /tasks/*
</text>
<text x="400" y="355" text-anchor="middle" font-family="system-ui, monospace" font-size="10" fill="#475569">
/sessions/*
</text>
<!-- Admin Endpoints -->
<rect x="520" y="280" width="200" height="80" fill="url(#adminGrad)" stroke="#fa709a" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="620" y="305" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#1e293b">
Admin Endpoints
</text>
<text x="620" y="325" text-anchor="middle" font-family="system-ui, monospace" font-size="10" fill="#475569">
/admin/*
</text>
<text x="620" y="340" text-anchor="middle" font-family="system-ui, monospace" font-size="10" fill="#475569">
/monitoring
</text>
<text x="620" y="355" text-anchor="middle" font-family="system-ui, monospace" font-size="10" fill="#475569">
/analytics
</text>
<!-- Arrows converging to service layer -->
<path d="M 180 360 L 180 380 L 400 380 L 400 400" stroke="#4a5568" stroke-width="2" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<path d="M 400 360 L 400 400" stroke="#4a5568" stroke-width="2" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<path d="M 620 360 L 620 380 L 400 380 L 400 400" stroke="#4a5568" stroke-width="2" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<!-- Service Layer -->
<rect x="250" y="400" width="300" height="70" fill="url(#serviceGrad)" stroke="#330867" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="400" y="425" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
Service Layer
</text>
<text x="400" y="445" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
• Session Manager
</text>
<text x="400" y="460" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
• Auth Service • Bot Service
</text>
<!-- Arrows to databases -->
<path d="M 400 470 L 400 485 L 180 485 L 180 500" stroke="#4a5568" stroke-width="2" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<path d="M 400 470 L 400 500" stroke="#4a5568" stroke-width="2" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<path d="M 400 470 L 400 485 L 620 485 L 620 500" stroke="#4a5568" stroke-width="2" fill="none" marker-end="url(#arrow)" opacity="0.7"/>
<!-- PostgreSQL -->
<rect x="80" y="500" width="200" height="70" fill="url(#dbGrad)" stroke="#38f9d7" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="180" y="525" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#1e293b">
PostgreSQL
</text>
<text x="180" y="545" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
Database
</text>
<text x="180" y="560" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#64748b">
Sessions • Users • Config
</text>
<!-- Valkey Cache -->
<rect x="300" y="500" width="200" height="70" fill="url(#dbGrad)" stroke="#38f9d7" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="400" y="525" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#1e293b">
Valkey
</text>
<text x="400" y="545" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
Cache
</text>
<text x="400" y="560" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#64748b">
Semantic • Session • Temp
</text>
<!-- Qdrant -->
<rect x="520" y="500" width="200" height="70" fill="url(#dbGrad)" stroke="#38f9d7" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="620" y="525" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#1e293b">
Qdrant
</text>
<text x="620" y="545" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
Vectors
</text>
<text x="620" y="560" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#64748b">
Embeddings • Search
</text>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1,224 @@
<svg width="600" height="700" viewBox="0 0 600 700" xmlns="http://www.w3.org/2000/svg">
<!-- Define gradients and effects -->
<defs>
<!-- Gradients for different stages -->
<linearGradient id="requestGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#667eea;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#764ba2;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="rateLimitGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#f59e0b;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#d97706;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="authGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#ef4444;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#dc2626;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="routeGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#8b5cf6;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#7c3aed;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="validateGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#06b6d4;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#0891b2;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="processGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#10b981;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#059669;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="formatGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#4facfe;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#00f2fe;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="responseGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#43e97b;stop-opacity:0.2" />
<stop offset="100%" style="stop-color:#38f9d7;stop-opacity:0.3" />
</linearGradient>
<!-- Success path gradient -->
<linearGradient id="successPath" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#10b981;stop-opacity:0.8" />
<stop offset="100%" style="stop-color:#34d399;stop-opacity:0.3" />
</linearGradient>
<!-- Failure path gradient -->
<linearGradient id="failPath" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#ef4444;stop-opacity:0.8" />
<stop offset="100%" style="stop-color:#f87171;stop-opacity:0.3" />
</linearGradient>
<!-- Arrow markers -->
<marker id="arrow" markerWidth="12" markerHeight="12" refX="11" refY="6" orient="auto">
<path d="M 0 0 L 12 6 L 0 12 L 3 6 Z" fill="#4a5568" opacity="0.7"/>
</marker>
<marker id="arrowSuccess" markerWidth="12" markerHeight="12" refX="11" refY="6" orient="auto">
<path d="M 0 0 L 12 6 L 0 12 L 3 6 Z" fill="#10b981" opacity="0.8"/>
</marker>
<marker id="arrowFail" markerWidth="12" markerHeight="12" refX="11" refY="6" orient="auto">
<path d="M 0 0 L 12 6 L 0 12 L 3 6 Z" fill="#ef4444" opacity="0.8"/>
</marker>
<!-- Drop shadow filter -->
<filter id="shadow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="2"/>
<feOffset dx="0" dy="2" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.15"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Background -->
<rect x="0" y="0" width="600" height="700" fill="#fafafa"/>
<!-- Title -->
<rect x="150" y="10" width="300" height="35" fill="rgba(99, 102, 241, 0.05)" rx="8"/>
<text x="300" y="33" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="18" font-weight="600" fill="#1e293b">
API Request Flow
</text>
<!-- HTTP Request -->
<rect x="200" y="60" width="200" height="50" fill="url(#requestGrad)" stroke="#667eea" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="300" y="85" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
HTTP Request
</text>
<text x="300" y="100" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
Client → Server
</text>
<!-- Arrow down -->
<path d="M 300 110 L 300 140" stroke="url(#successPath)" stroke-width="3" fill="none" marker-end="url(#arrowSuccess)" opacity="0.7"/>
<!-- Rate Limit -->
<rect x="200" y="140" width="200" height="60" fill="url(#rateLimitGrad)" stroke="#f59e0b" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="300" y="165" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
Rate Limit
</text>
<text x="300" y="185" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
Check request limits
</text>
<!-- Pass/Fail paths -->
<path d="M 300 200 L 300 230" stroke="url(#successPath)" stroke-width="3" fill="none" marker-end="url(#arrowSuccess)" opacity="0.7"/>
<text x="320" y="215" text-anchor="start" font-family="system-ui, sans-serif" font-size="10" font-weight="500" fill="#059669">Pass</text>
<path d="M 400 170 L 480 170 L 480 650" stroke="url(#failPath)" stroke-width="2" stroke-dasharray="5,3" fill="none" marker-end="url(#arrowFail)" opacity="0.5"/>
<text x="420" y="165" text-anchor="start" font-family="system-ui, sans-serif" font-size="9" fill="#dc2626">429 Too Many</text>
<!-- Auth -->
<rect x="200" y="230" width="200" height="60" fill="url(#authGrad)" stroke="#ef4444" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="300" y="255" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
Auth
</text>
<text x="300" y="275" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
Validate token/session
</text>
<!-- Pass/Fail paths -->
<path d="M 300 290 L 300 320" stroke="url(#successPath)" stroke-width="3" fill="none" marker-end="url(#arrowSuccess)" opacity="0.7"/>
<text x="320" y="305" text-anchor="start" font-family="system-ui, sans-serif" font-size="10" font-weight="500" fill="#059669">Valid</text>
<path d="M 400 260 L 460 260 L 460 650" stroke="url(#failPath)" stroke-width="2" stroke-dasharray="5,3" fill="none" marker-end="url(#arrowFail)" opacity="0.5"/>
<text x="420" y="255" text-anchor="start" font-family="system-ui, sans-serif" font-size="9" fill="#dc2626">401 Unauthorized</text>
<!-- Route -->
<rect x="200" y="320" width="200" height="60" fill="url(#routeGrad)" stroke="#8b5cf6" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="300" y="345" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
Route
</text>
<text x="300" y="365" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
Match endpoint pattern
</text>
<!-- Arrow down -->
<path d="M 300 380 L 300 410" stroke="url(#successPath)" stroke-width="3" fill="none" marker-end="url(#arrowSuccess)" opacity="0.7"/>
<path d="M 400 350 L 440 350 L 440 650" stroke="url(#failPath)" stroke-width="2" stroke-dasharray="5,3" fill="none" marker-end="url(#arrowFail)" opacity="0.5"/>
<text x="420" y="345" text-anchor="start" font-family="system-ui, sans-serif" font-size="9" fill="#dc2626">404 Not Found</text>
<!-- Validate -->
<rect x="200" y="410" width="200" height="60" fill="url(#validateGrad)" stroke="#06b6d4" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="300" y="435" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
Validate
</text>
<text x="300" y="455" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
Check request body
</text>
<!-- Pass/Fail paths -->
<path d="M 300 470 L 300 500" stroke="url(#successPath)" stroke-width="3" fill="none" marker-end="url(#arrowSuccess)" opacity="0.7"/>
<text x="320" y="485" text-anchor="start" font-family="system-ui, sans-serif" font-size="10" font-weight="500" fill="#059669">Valid</text>
<path d="M 400 440 L 420 440 L 420 650" stroke="url(#failPath)" stroke-width="2" stroke-dasharray="5,3" fill="none" marker-end="url(#arrowFail)" opacity="0.5"/>
<text x="425" y="435" text-anchor="start" font-family="system-ui, sans-serif" font-size="9" fill="#dc2626">400 Bad Request</text>
<!-- Process -->
<rect x="200" y="500" width="200" height="60" fill="url(#processGrad)" stroke="#10b981" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="300" y="525" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
Process
</text>
<text x="300" y="545" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
Execute business logic
</text>
<!-- Arrow down -->
<path d="M 300 560 L 300 590" stroke="url(#successPath)" stroke-width="3" fill="none" marker-end="url(#arrowSuccess)" opacity="0.7"/>
<!-- Format -->
<rect x="200" y="590" width="200" height="60" fill="url(#formatGrad)" stroke="#00f2fe" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="300" y="615" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
Format
</text>
<text x="300" y="635" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
JSON response
</text>
<!-- Arrow down -->
<path d="M 300 650 L 300 680" stroke="url(#successPath)" stroke-width="3" fill="none" marker-end="url(#arrowSuccess)" opacity="0.7"/>
<!-- HTTP Response -->
<rect x="200" y="680" width="200" height="50" fill="url(#responseGrad)" stroke="#38f9d7" stroke-width="2" rx="8" filter="url(#shadow)"/>
<text x="300" y="705" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#1e293b">
HTTP Response
</text>
<text x="300" y="720" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#475569">
Server → Client
</text>
<!-- Error Response box -->
<rect x="410" y="650" width="100" height="30" fill="rgba(239, 68, 68, 0.1)" stroke="#ef4444" stroke-width="1.5" rx="6"/>
<text x="460" y="670" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" font-weight="500" fill="#dc2626">
Error Response
</text>
<!-- Side labels -->
<g transform="translate(50, 380)">
<text x="0" y="0" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#64748b" transform="rotate(-90)">
Request Pipeline
</text>
</g>
<!-- Status indicators -->
<g transform="translate(80, 150)">
<circle cx="0" cy="0" r="4" fill="#10b981"/>
<text x="10" y="4" font-family="system-ui, sans-serif" font-size="9" fill="#475569">Success path</text>
</g>
<g transform="translate(80, 170)">
<circle cx="0" cy="0" r="4" fill="#ef4444"/>
<text x="10" y="4" font-family="system-ui, sans-serif" font-size="9" fill="#475569">Error path</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB