Files
OmniRoute/docs/diagrams/resilience-layers.svg
Diego Rodrigues de Sa e Souza a856e3dd20 docs(readme): unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal (#7769)
* docs(readme): width + content overhaul — uniform tables, full CLI grid, condensed What's New

- All remaining spacer-calibrated tables re-targeted +100px so every table
  clamps to the same full column width as the Why OmniRoute table.
- Free-tier section: the 4 text bullets are gone — the animated budget card
  already carries all of it.
- What's New: every highlight condensed to a 1-2 line bullet (links kept).
- Compatible CLIs: the grid now lists all 25 tools from the dashboard
  registries (19 CLI Code's + 6 CLI Agents — Cline, Roo Code, Aider,
  ForgeCode, jcode, DeepSeek TUI, CodeWhale, Smelt, Pi, Grok Build, Hermes
  Agent, Goose, Open Interpreter, Warp AI, Agent Deck…) in 2 full-width
  rows; tools without a brand asset use a neutral terminal glyph
  (public/providers/cli-generic.svg) — no invented logos.
- Major-labs providers grid: 3x6 -> 2x9 full-width rows.
- Free Forever: 2 rows -> a single 7-card full-width row.
- Explore More section removed; Dashboard screenshots promoted to their own
  top-level section.

* docs(readme): force full-width card grids via in-cell spacers (GitHub strips td width)

* docs(readme): CLI grid 3 balanced rows, dark-safe Cline/Roo icons, fix 251->259 heading

* docs(readme): replace img spacers with NBSP runs — img max-width:100% collapses all-or-nothing past the container; text min-content never does

* docs(readme): calibrate card-grid NBSP runs to measured 3.14px (match Why table width); Roo icon via gh-dark-mode-only

* docs(readme): fine-tune markdown-table NBSP runs to measured widths (all ~1000px)

* docs(readme): sync stale counts to v3.8.49 reality — 268 providers (regen reference), 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, 84 executors; fix 251-era anchors + nav

* docs(readme): animated hero card + The Promise six-pillar card — embed replaces hero text block, six static badges and the promise HTML table; all numbers from the v3.8.49 audit

* docs(diagrams): make hero/promise card reveals resilient — resting state is the final composition, entrance animates via 0s-begin hold pattern (GitHub camo drops offset-begin one-shots)

* docs(diagrams): pause-safe animation cycles — first frame is the finished composition (Chrome pause-animated-images freezes SVG imgs at t=0, where animation values override static attrs); hero/promise drop entrance reveals, budget bar/strike/dot cycles start at rest state

* docs(readme): unify all animated cards on the flat family style (no outer border/rounded frame/top strip) + fuse hero with the budget card at the top — star CTA back to text, money section moved under the hero, cli-terminal flattened with a t0 poster of the completed screen

* docs(readme): Why OmniRoute as an animated 10-row pain-vs-fix ledger card — extends the 6 original rows with resilience, key pools, local-first privacy and live analytics

* docs(readme): animated 18-strategy flow grid under the strategies table — one micro-stage per routing strategy, static tracks readable on the first frame

* docs(readme): blank line between strategies-grid img and the auto-combo sub note — the img HTML block was swallowing the note, rendering its markdown raw

* docs(readme): Private & Local-First as an 11-row guarantee ledger card — the 5 original bullets plus no-signup, loopback-only routes, header scrubbing, opt-in PII, sanitized errors and local audit trail, each with a receipt chip

* docs(readme): rebuild the resilience card — 3 self-healing layers with real mechanics (breaker states + thresholds, key cooldown with x2 backoff, model lockout) replacing the always-on combo card and the 3-row table

* docs(diagrams): rebuild cli-terminal as a compact half-height real terminal (1200x350) — pure terminal theme, real CLI commands and data tied to live counts, scrolling ticker of real subcommands

* docs(changelog): maintenance fragment for the README animated-card overhaul (#7769)
2026-07-19 12:11:13 -03:00

22 lines
22 KiB
XML

<svg viewBox="0 0 1200 726" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="OmniRoute resilience — three independent self-healing layers, the right layer for the right failure. Layer 1, provider circuit breaker (scope: whole provider): trips only on 408/500/502/503/504, thresholds of 3 fails for OAuth, 5 for API-key, 2 for local providers, reset timeouts of 60, 30 and 15 seconds into a HALF-OPEN probe, lazy recovery where reads refresh expired state; while OPEN the combo reroutes to the next provider, then a probe closes the breaker. Layer 2, connection cooldown (scope: one key or account): base cooldown 5 seconds OAuth and 3 seconds API-key, exponential backoff times two per repeated failure with an anti-thundering-herd guard, 429 honors Retry-After and reset headers, success calls clearAccountError; one rate-limited key is skipped while the other keys keep serving. Layer 3, model lockout (scope: one model): per-model 429, local 404 or mode denials lock just that model — a locked model is not a dead key, other models keep serving instantly. Terminal states banned, expired and credits_exhausted are not cooldowns and wait for the operator.">
<desc>Animated resilience card: three stacked layer panels, each replaying its healing loop — breaker states cycling CLOSED, OPEN, HALF-OPEN; a cooling key with backoff while other keys serve; a locked model while sibling models keep serving. First frame is fully readable.</desc>
<defs>
<pattern id="gridPaperR" width="32" height="32" patternUnits="userSpaceOnUse">
<path d="M 32 0 L 0 0 0 32" fill="none" stroke="#ffffff" stroke-opacity="0.06" stroke-width="1"/>
</pattern>
<radialGradient id="bgGlowR" cx="24%" cy="12%" r="55%">
<stop offset="0%" stop-color="#e54d5e" stop-opacity="0.10"/>
<stop offset="55%" stop-color="#8b5cf6" stop-opacity="0.05"/>
<stop offset="100%" stop-color="#6366f1" stop-opacity="0"/>
</radialGradient>
</defs>
<rect width="1200" height="726" fill="#0b0e14"/>
<rect width="1200" height="726" fill="url(#gridPaperR)"/>
<rect width="1200" height="726" fill="url(#bgGlowR)"/>
<text x="40" y="56" font-family="Consolas, 'Courier New', monospace" font-size="13" letter-spacing="2.5" fill="#a78bfa">RESILIENCE &#183; 3 SELF-HEALING LAYERS</text>
<line x1="392" y1="51" x2="856" y2="51" stroke="#232b38" stroke-width="1.5"/>
<text x="40" y="100" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="23" font-weight="600" fill="#c9d1d9">The <tspan fill="#7ee787" font-weight="800">right layer</tspan> for the right failure — never kill more than <tspan fill="#a78bfa" font-weight="800">what actually broke</tspan>.</text>
<g font-family="Consolas, 'Courier New', monospace" font-size="9"><rect x="878" y="34" width="282" height="80" rx="10" fill="none" stroke="#a78bfa" stroke-opacity="0.5"/><text x="890" y="48" fill="#a78bfa" letter-spacing="1">PROVIDER</text><rect x="938" y="56" width="176" height="50" rx="8" fill="none" stroke="#fdcb6e" stroke-opacity="0.55"/><text x="948" y="70" fill="#fdcb6e" letter-spacing="1">CONNECTION / KEY</text><rect x="988" y="78" width="88" height="22" rx="6" fill="none" stroke="#00cec9" stroke-opacity="0.6"/><text x="998" y="92" fill="#00cec9" letter-spacing="1">MODEL</text></g>
<rect x="40" y="136" width="1120" height="168" rx="14" fill="#161b22" stroke="#ffffff" stroke-opacity="0.07" stroke-width="1"/><text x="64" y="170" font-family="Consolas, 'Courier New', monospace" font-size="10.5" letter-spacing="1.5" fill="#a78bfa">LAYER 1 &#183; SCOPE: WHOLE PROVIDER</text><text x="64" y="198" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="17.5" font-weight="800" fill="#c9d1d9">Provider circuit breaker</text><text x="64" y="224" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="12.5" fill="#71717a">isolate a provider failing upstream —</text><text x="64" y="242" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="12.5" fill="#71717a">reroute now, auto-probe to recover</text><circle cx="856" cy="168.5" r="2" fill="#a78bfa"/><text x="868" y="172" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">trips only on 408 &#183; 500 &#183; 502 &#183; 503 &#183; 504</text><circle cx="856" cy="198.5" r="2" fill="#a78bfa"/><text x="868" y="202" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">threshold — oauth 3&#215; &#183; api-key 5&#215; &#183; local 2&#215;</text><circle cx="856" cy="228.5" r="2" fill="#a78bfa"/><text x="868" y="232" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">reset — 60s &#183; 30s &#183; 15s &#8594; HALF-OPEN probe</text><circle cx="856" cy="258.5" r="2" fill="#a78bfa"/><text x="868" y="262" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">lazy recovery — reads refresh expired state</text><circle cx="404" cy="220" r="13" fill="none" stroke="#c9d1d9" stroke-width="1.6"/><circle cx="404" cy="220" r="4" fill="#c9d1d9"/><text x="404" y="250" text-anchor="middle" font-family="Consolas, 'Courier New', monospace" font-size="9" fill="#71717a">router</text><rect x="470" y="164" width="152" height="50" rx="10" fill="#1c2330" stroke="#ffffff" stroke-opacity="0.1"/><text x="486" y="186" font-family="Consolas, 'Courier New', monospace" font-size="11.5" fill="#c9d1d9">provider A</text><text x="486" y="204" font-family="Consolas, 'Courier New', monospace" font-size="10" fill="#f87171">fails &#215;5</text><rect x="470" y="240" width="152" height="42" rx="10" fill="#1c2330" stroke="#7ee787" stroke-opacity="0.45"/><text x="486" y="266" font-family="Consolas, 'Courier New', monospace" font-size="11.5" fill="#7ee787">provider B &#8592; next</text><path d="M 418,220 C 442,220 446,189 466,189" fill="none" stroke="#8b5cf6" stroke-opacity="0.5" stroke-width="1.6"/><path d="M 418,220 C 442,220 446,261 466,261" fill="none" stroke="#71717a" stroke-opacity="0.5" stroke-width="1.1" stroke-dasharray="3 3"/><rect x="656" y="156" width="128" height="24" rx="12" fill="#0f141d" stroke="#7ee787" stroke-opacity="0.4"/><circle cx="672" cy="168" r="4.5" fill="#7ee787"><animate attributeName="opacity" calcMode="discrete" values="1;0.18;1;1" keyTimes="0.000;0.280;0.820;1.000" dur="18s" repeatCount="indefinite"/></circle><text x="686" y="172" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#7ee787">CLOSED</text><rect x="656" y="186" width="128" height="24" rx="12" fill="#0f141d" stroke="#f87171" stroke-opacity="0.4"/><circle cx="672" cy="198" r="4.5" fill="#f87171"><animate attributeName="opacity" calcMode="discrete" values="0.18;1;0.18;0.18" keyTimes="0.000;0.280;0.620;1.000" dur="18s" repeatCount="indefinite"/></circle><text x="686" y="202" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#f87171">OPEN</text><rect x="656" y="216" width="128" height="24" rx="12" fill="#0f141d" stroke="#fbbf24" stroke-opacity="0.4"/><circle cx="672" cy="228" r="4.5" fill="#fbbf24"><animate attributeName="opacity" calcMode="discrete" values="0.18;1;0.18;0.18" keyTimes="0.000;0.620;0.820;1.000" dur="18s" repeatCount="indefinite"/></circle><text x="686" y="232" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#fbbf24">HALF-OPEN</text><circle r="2.8" fill="#a78bfa" opacity="0"><animateMotion path="M 418,220 C 442,220 446,189 466,189" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.03;0.11;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.03;0.045;0.095;0.11;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#a78bfa" opacity="0"><animateMotion path="M 418,220 C 442,220 446,189 466,189" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.09;0.16999999999999998;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.09;0.105;0.15499999999999997;0.16999999999999998;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#a78bfa" opacity="0"><animateMotion path="M 418,220 C 442,220 446,189 466,189" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.15;0.22999999999999998;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.15;0.16499999999999998;0.21499999999999997;0.22999999999999998;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.23;0.24000000000000002;0.27999999999999997;0.29;1" begin="0s" dur="18s" repeatCount="indefinite"/><g stroke="#f87171" stroke-width="2.6" stroke-linecap="round"><line x1="594" y1="183" x2="606" y2="195"/><line x1="606" y1="183" x2="594" y2="195"/></g></g><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 418,220 C 442,220 446,261 466,261" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.33;0.44;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.33;0.34500000000000003;0.425;0.44;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 418,220 C 442,220 446,261 466,261" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.4;0.51;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.4;0.41500000000000004;0.495;0.51;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 418,220 C 442,220 446,261 466,261" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.47000000000000003;0.5800000000000001;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.47000000000000003;0.48500000000000004;0.5650000000000001;0.5800000000000001;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#fbbf24" opacity="0"><animateMotion path="M 418,220 C 442,220 446,189 466,189" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.66;0.74;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.66;0.675;0.725;0.74;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.76;0.77;0.83;0.84;1" begin="0s" dur="18s" repeatCount="indefinite"/><g stroke="#7ee787" stroke-width="2.8" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M 593,189 L 598,194 L 607,183"/></g></g><rect x="40" y="318" width="1120" height="168" rx="14" fill="#161b22" stroke="#ffffff" stroke-opacity="0.07" stroke-width="1"/><text x="64" y="352" font-family="Consolas, 'Courier New', monospace" font-size="10.5" letter-spacing="1.5" fill="#fdcb6e">LAYER 2 &#183; SCOPE: ONE KEY / ACCOUNT</text><text x="64" y="380" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="17.5" font-weight="800" fill="#c9d1d9">Connection cooldown</text><text x="64" y="406" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="12.5" fill="#71717a">skip one rate-limited key while the</text><text x="64" y="424" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="12.5" fill="#71717a">other keys keep serving the provider</text><circle cx="856" cy="350.5" r="2" fill="#fdcb6e"/><text x="868" y="354" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">base cooldown — oauth 5s &#183; api-key 3s</text><circle cx="856" cy="380.5" r="2" fill="#fdcb6e"/><text x="868" y="384" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">repeat fails — backoff &#215;2 (anti-herd guard)</text><circle cx="856" cy="410.5" r="2" fill="#fdcb6e"/><text x="868" y="414" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">429 honors Retry-After / reset headers</text><circle cx="856" cy="440.5" r="2" fill="#fdcb6e"/><text x="868" y="444" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">success &#8594; clearAccountError() resets all</text><circle cx="384" cy="402" r="4" fill="#c9d1d9"/><rect x="404" y="336" width="270" height="134" rx="10" fill="none" stroke="#ffffff" stroke-opacity="0.09"/><text x="416" y="352" font-family="Consolas, 'Courier New', monospace" font-size="9" fill="#71717a">provider &#183; 3 keys</text><rect x="420" y="362" width="120" height="26" rx="6" fill="#1c2330" stroke="#f87171" stroke-opacity="0.55"/><text x="432" y="379" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#c9d1d9">key-1</text><text x="512" y="379" font-family="Consolas, 'Courier New', monospace" font-size="10" fill="#f87171">429</text><rect x="420" y="398" width="120" height="26" rx="6" fill="#1c2330" stroke="#7ee787" stroke-opacity="0.55"/><text x="432" y="415" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#c9d1d9">key-2</text><rect x="420" y="434" width="120" height="26" rx="6" fill="#1c2330" stroke="#ffffff" stroke-opacity="0.1"/><text x="432" y="451" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#c9d1d9">key-3</text><rect x="556" y="363" width="112" height="24" rx="12" fill="#0f141d" stroke="#fbbf24" stroke-opacity="0.45"/><text x="568" y="379" font-family="Consolas, 'Courier New', monospace" font-size="9.5" fill="#fbbf24">cooling &#215;2&#8319;</text><rect x="556" y="392" width="112" height="4" rx="2" fill="#0f141d"/><rect x="556" y="392" width="112" height="4" rx="2" fill="#fbbf24"><animate attributeName="width" values="112;0;0;112" keyTimes="0;0.7;0.78;1" dur="18s" repeatCount="indefinite"/></rect><path d="M 390,402 C 404,402 404,375 416,375" fill="none" stroke="#71717a" stroke-opacity="0.45" stroke-width="1.1" stroke-dasharray="3 3"/><path d="M 390,402 C 404,402 404,411 416,411" fill="none" stroke="#8b5cf6" stroke-opacity="0.5" stroke-width="1.6"/><circle r="2.8" fill="#a78bfa" opacity="0"><animateMotion path="M 390,402 C 404,402 404,375 416,375" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.03;0.1;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.03;0.045;0.085;0.1;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.1;0.11;0.15;0.16;1" begin="0s" dur="18s" repeatCount="indefinite"/><g stroke="#f87171" stroke-width="2.6" stroke-linecap="round"><line x1="524" y1="369" x2="536" y2="381"/><line x1="536" y1="369" x2="524" y2="381"/></g></g><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 390,402 C 404,402 404,411 416,411" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.2;0.29;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.2;0.21500000000000002;0.27499999999999997;0.29;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 390,402 C 404,402 404,411 416,411" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.29000000000000004;0.38;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.29000000000000004;0.30500000000000005;0.365;0.38;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 390,402 C 404,402 404,411 416,411" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.38;0.47;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.38;0.395;0.45499999999999996;0.47;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 390,402 C 404,402 404,411 416,411" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.47000000000000003;0.56;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.47000000000000003;0.48500000000000004;0.545;0.56;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 390,402 C 404,402 404,375 416,375" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.8;0.88;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.8;0.8150000000000001;0.865;0.88;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.89;0.9;0.96;0.97;1" begin="0s" dur="18s" repeatCount="indefinite"/><g stroke="#7ee787" stroke-width="2.8" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M 523,375 L 528,380 L 537,369"/></g></g><rect x="40" y="500" width="1120" height="168" rx="14" fill="#161b22" stroke="#ffffff" stroke-opacity="0.07" stroke-width="1"/><text x="64" y="534" font-family="Consolas, 'Courier New', monospace" font-size="10.5" letter-spacing="1.5" fill="#00cec9">LAYER 3 &#183; SCOPE: ONE MODEL</text><text x="64" y="562" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="17.5" font-weight="800" fill="#c9d1d9">Model lockout</text><text x="64" y="588" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="12.5" fill="#71717a">quarantine a single model — never kill</text><text x="64" y="606" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="12.5" fill="#71717a">the whole connection for one 429</text><circle cx="856" cy="532.5" r="2" fill="#00cec9"/><text x="868" y="536" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">scope — provider + connection + model</text><circle cx="856" cy="562.5" r="2" fill="#00cec9"/><text x="868" y="566" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">per-model 429 &#183; local 404 &#183; mode denials</text><circle cx="856" cy="592.5" r="2" fill="#00cec9"/><text x="868" y="596" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">locked model &#8800; dead key</text><circle cx="856" cy="622.5" r="2" fill="#00cec9"/><text x="868" y="626" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#9aa3b0">other models keep serving instantly</text><rect x="396" y="560" width="112" height="48" rx="10" fill="#1c2330" stroke="#ffffff" stroke-opacity="0.1"/><text x="412" y="588" font-family="Consolas, 'Courier New', monospace" font-size="11.5" fill="#c9d1d9">key-1</text><rect x="580" y="530" width="130" height="28" rx="6" fill="#1c2330" stroke="#7ee787" stroke-opacity="0.5"/><text x="594" y="548" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#c9d1d9">model-a</text><g transform="translate(682,538)" stroke="#7ee787" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M 0,6 L 3.5,9.5 L 10,1.5"/></g><rect x="580" y="570" width="130" height="28" rx="6" fill="#1c2330" stroke="#f87171" stroke-opacity="0.5"/><text x="594" y="588" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#c9d1d9">model-b</text><g transform="translate(682,577)" stroke="#f87171" stroke-width="1.6" fill="none" stroke-linecap="round"><rect x="0" y="5" width="11" height="8" rx="1.5"/><path d="M 2,5 L 2,3 A 3.5,3.5 0 0 1 9,3 L 9,5"/></g><rect x="580" y="610" width="130" height="28" rx="6" fill="#1c2330" stroke="#7ee787" stroke-opacity="0.5"/><text x="594" y="628" font-family="Consolas, 'Courier New', monospace" font-size="10.5" fill="#c9d1d9">model-c</text><g transform="translate(682,618)" stroke="#7ee787" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M 0,6 L 3.5,9.5 L 10,1.5"/></g><path d="M 512,584 C 540,584 548,544 576,544" fill="none" stroke="#8b5cf6" stroke-opacity="0.5" stroke-width="1.6"/><path d="M 512,584 C 545,584 545,584 576,584" fill="none" stroke="#71717a" stroke-opacity="0.45" stroke-width="1.1" stroke-dasharray="3 3"/><path d="M 512,584 C 540,584 548,624 576,624" fill="none" stroke="#8b5cf6" stroke-opacity="0.5" stroke-width="1.6"/><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 512,584 C 540,584 548,544 576,544" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.05;0.15;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.05;0.065;0.135;0.15;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 512,584 C 540,584 548,544 576,544" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.21000000000000002;0.31;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.21000000000000002;0.22500000000000003;0.295;0.31;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#a78bfa" opacity="0"><animateMotion path="M 512,584 C 545,584 545,584 576,584" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.38;0.47;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.38;0.395;0.45499999999999996;0.47;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.47;0.48;0.52;0.53;1" begin="0s" dur="18s" repeatCount="indefinite"/><g stroke="#f87171" stroke-width="2.6" stroke-linecap="round"><line x1="550" y1="578" x2="562" y2="590"/><line x1="562" y1="578" x2="550" y2="590"/></g></g><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 512,584 C 540,584 548,624 576,624" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.58;0.68;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.58;0.595;0.665;0.68;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle><circle r="2.8" fill="#7ee787" opacity="0"><animateMotion path="M 512,584 C 540,584 548,624 576,624" begin="0s" dur="18s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.74;0.8400000000000001;1" calcMode="linear"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.74;0.755;0.8250000000000001;0.8400000000000001;1" begin="0s" dur="18s" repeatCount="indefinite"/></circle>
<text x="40" y="708" font-family="Consolas, 'Courier New', monospace" font-size="11" fill="#71717a">which failure trips what &#8594; <tspan fill="#a78bfa">5xx / 408 : breaker</tspan> &#183; <tspan fill="#fdcb6e">key 429 / 401 : cooldown</tspan> &#183; <tspan fill="#00cec9">one-model 429 / 404 : lockout</tspan> &#183; banned / expired / credits : terminal (operator)</text>
</svg>