Files
libnovel/v3/docs/d2/architecture.svg
Admin 5b27d501af feat(v3): Caddy hardening, Watchtower, scrape fixes, docs diagrams
- Caddy: custom image with caddy-ratelimit plugin, security headers
  (X-Frame-Options, HSTS, CSP-adjacent, etc.), per-IP rate limiting on
  auth/scrape/global zones, static error pages (502/503/504), fix routing
  to remove /api/scrape/* and /api/chapter-text-preview/* direct-to-backend
  (were bypassing SvelteKit auth middleware)
- docker-compose: Caddy build context + error volume, Watchtower service
  (label-enable mode, 5 min poll), watchtower labels on backend/runner/ui
- Scraper: ScrapeChapterList uses retryGet (9 attempts, Retry-After backoff)
  to fix 429-induced chapter list failures; upTo param stops pagination early
  for range scrapes
- UI: Browse→Catalogue rename (routes, API, links), admin scrape page
  Continue/Retry buttons, +error.svelte branded error page, type cleanup
  (removed dead exports, added BookPreviewMeta/BookPreviewResponse to scraper.ts)
- Meilisearch: meta_updated field, sort=update fix, facet distribution
- Docs: reorganise into docs/d2/ and docs/mermaid/ subdirectories, update
  all diagrams to reflect Caddy/Watchtower/routing changes, add
  api-routing.d2 ownership map with auth-level colour coding, regenerate SVGs
2026-03-22 21:10:38 +05:00

130 lines
58 KiB
XML

<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" data-d2-version="0.7.1" preserveAspectRatio="xMinYMin meet" viewBox="0 0 3735 2292"><svg class="d2-271920619 d2-svg" width="3735" height="2292" viewBox="-101 -85 3735 2292"><rect x="-101.000000" y="-85.000000" width="3735.000000" height="2292.000000" rx="0.000000" fill="#FFFFFF" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-271920619 .text {
font-family: "d2-271920619-font-regular";
}
@font-face {
font-family: d2-271920619-font-regular;
src: url("data:application/font-woff;base64,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");
}
.d2-271920619 .text-bold {
font-family: "d2-271920619-font-bold";
}
@font-face {
font-family: d2-271920619-font-bold;
src: url("data:application/font-woff;base64,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");
}
.d2-271920619 .text-italic {
font-family: "d2-271920619-font-italic";
}
@font-face {
font-family: d2-271920619-font-italic;
src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-271920619 .fill-N1{fill:#0A0F25;}
.d2-271920619 .fill-N2{fill:#676C7E;}
.d2-271920619 .fill-N3{fill:#9499AB;}
.d2-271920619 .fill-N4{fill:#CFD2DD;}
.d2-271920619 .fill-N5{fill:#DEE1EB;}
.d2-271920619 .fill-N6{fill:#EEF1F8;}
.d2-271920619 .fill-N7{fill:#FFFFFF;}
.d2-271920619 .fill-B1{fill:#0D32B2;}
.d2-271920619 .fill-B2{fill:#0D32B2;}
.d2-271920619 .fill-B3{fill:#E3E9FD;}
.d2-271920619 .fill-B4{fill:#E3E9FD;}
.d2-271920619 .fill-B5{fill:#EDF0FD;}
.d2-271920619 .fill-B6{fill:#F7F8FE;}
.d2-271920619 .fill-AA2{fill:#4A6FF3;}
.d2-271920619 .fill-AA4{fill:#EDF0FD;}
.d2-271920619 .fill-AA5{fill:#F7F8FE;}
.d2-271920619 .fill-AB4{fill:#EDF0FD;}
.d2-271920619 .fill-AB5{fill:#F7F8FE;}
.d2-271920619 .stroke-N1{stroke:#0A0F25;}
.d2-271920619 .stroke-N2{stroke:#676C7E;}
.d2-271920619 .stroke-N3{stroke:#9499AB;}
.d2-271920619 .stroke-N4{stroke:#CFD2DD;}
.d2-271920619 .stroke-N5{stroke:#DEE1EB;}
.d2-271920619 .stroke-N6{stroke:#EEF1F8;}
.d2-271920619 .stroke-N7{stroke:#FFFFFF;}
.d2-271920619 .stroke-B1{stroke:#0D32B2;}
.d2-271920619 .stroke-B2{stroke:#0D32B2;}
.d2-271920619 .stroke-B3{stroke:#E3E9FD;}
.d2-271920619 .stroke-B4{stroke:#E3E9FD;}
.d2-271920619 .stroke-B5{stroke:#EDF0FD;}
.d2-271920619 .stroke-B6{stroke:#F7F8FE;}
.d2-271920619 .stroke-AA2{stroke:#4A6FF3;}
.d2-271920619 .stroke-AA4{stroke:#EDF0FD;}
.d2-271920619 .stroke-AA5{stroke:#F7F8FE;}
.d2-271920619 .stroke-AB4{stroke:#EDF0FD;}
.d2-271920619 .stroke-AB5{stroke:#F7F8FE;}
.d2-271920619 .background-color-N1{background-color:#0A0F25;}
.d2-271920619 .background-color-N2{background-color:#676C7E;}
.d2-271920619 .background-color-N3{background-color:#9499AB;}
.d2-271920619 .background-color-N4{background-color:#CFD2DD;}
.d2-271920619 .background-color-N5{background-color:#DEE1EB;}
.d2-271920619 .background-color-N6{background-color:#EEF1F8;}
.d2-271920619 .background-color-N7{background-color:#FFFFFF;}
.d2-271920619 .background-color-B1{background-color:#0D32B2;}
.d2-271920619 .background-color-B2{background-color:#0D32B2;}
.d2-271920619 .background-color-B3{background-color:#E3E9FD;}
.d2-271920619 .background-color-B4{background-color:#E3E9FD;}
.d2-271920619 .background-color-B5{background-color:#EDF0FD;}
.d2-271920619 .background-color-B6{background-color:#F7F8FE;}
.d2-271920619 .background-color-AA2{background-color:#4A6FF3;}
.d2-271920619 .background-color-AA4{background-color:#EDF0FD;}
.d2-271920619 .background-color-AA5{background-color:#F7F8FE;}
.d2-271920619 .background-color-AB4{background-color:#EDF0FD;}
.d2-271920619 .background-color-AB5{background-color:#F7F8FE;}
.d2-271920619 .color-N1{color:#0A0F25;}
.d2-271920619 .color-N2{color:#676C7E;}
.d2-271920619 .color-N3{color:#9499AB;}
.d2-271920619 .color-N4{color:#CFD2DD;}
.d2-271920619 .color-N5{color:#DEE1EB;}
.d2-271920619 .color-N6{color:#EEF1F8;}
.d2-271920619 .color-N7{color:#FFFFFF;}
.d2-271920619 .color-B1{color:#0D32B2;}
.d2-271920619 .color-B2{color:#0D32B2;}
.d2-271920619 .color-B3{color:#E3E9FD;}
.d2-271920619 .color-B4{color:#E3E9FD;}
.d2-271920619 .color-B5{color:#EDF0FD;}
.d2-271920619 .color-B6{color:#F7F8FE;}
.d2-271920619 .color-AA2{color:#4A6FF3;}
.d2-271920619 .color-AA4{color:#EDF0FD;}
.d2-271920619 .color-AA5{color:#F7F8FE;}
.d2-271920619 .color-AB4{color:#EDF0FD;}
.d2-271920619 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker-d2-271920619);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker-d2-271920619);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark-d2-271920619);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker-d2-271920619);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark-d2-271920619);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal-d2-271920619);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal-d2-271920619);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright-d2-271920619);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]></style><g class="bm92ZWxmaXJl"><g class="shape" ><path d="M 3340 1647 C 3340 1648 3339 1649 3338 1649 C 3324 1650 3313 1661 3313 1675 C 3313 1690 3326 1702 3342 1702 H 3450 C 3467 1702 3481 1689 3481 1674 C 3481 1659 3468 1647 3452 1646 C 3451 1646 3450 1645 3449 1644 C 3445 1629 3429 1618 3409 1618 C 3396 1618 3385 1623 3377 1630 C 3376 1631 3375 1631 3374 1631 C 3371 1630 3368 1630 3365 1630 C 3352 1630 3341 1637 3340 1647 Z" stroke="#0D32B2" fill="#f0f4ff" class=" stroke-B1" style="stroke-width:2;" /></g><text x="3395.796000" y="1681.516000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">novelfire.net</text></g><g class="a29rb3Jv"><g class="shape" ><path d="M 3320 1791 C 3320 1792 3318 1793 3317 1793 C 3298 1794 3283 1805 3283 1819 C 3283 1834 3300 1846 3321 1846 H 3467 C 3490 1846 3509 1833 3509 1818 C 3509 1803 3492 1791 3470 1790 C 3468 1790 3467 1789 3467 1788 C 3462 1773 3440 1762 3413 1762 C 3396 1762 3380 1767 3370 1774 C 3369 1775 3367 1775 3366 1775 C 3362 1774 3358 1774 3354 1774 C 3336 1774 3322 1781 3320 1791 Z" stroke="#0D32B2" fill="#f0f4ff" class=" stroke-B1" style="stroke-width:2;" /></g><text x="3395.547000" y="1825.516000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Kokoro-FastAPI TTS</text></g><g class="bGV0c2VuY3J5cHQ="><g class="shape" ><path d="M 1573 275 C 1573 276 1572 277 1571 277 C 1557 278 1545 289 1545 303 C 1545 318 1558 330 1574 330 H 1683 C 1700 330 1714 317 1714 302 C 1714 287 1701 275 1685 274 C 1684 274 1683 273 1682 272 C 1678 257 1661 246 1642 246 C 1629 246 1618 251 1610 258 C 1609 259 1608 259 1607 259 C 1604 258 1601 258 1598 258 C 1585 258 1574 265 1573 275 Z" stroke="#0D32B2" fill="#f0f4ff" class=" stroke-B1" style="stroke-width:2;" /></g><text x="1629.205500" y="309.516000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Let&#39;s Encrypt</text></g><g class="YnJvd3Nlcg=="><g class="shape" ><path d="M 140 632 H 0 V 631 C 0 615 15 601 40 594 C 26 588 18 579 18 569 C 18 553 41 539 70 539 C 98 539 122 553 122 569 C 122 579 114 588 101 594 C 125 601 141 615 141 631 V 632 H 140 Z" stroke="#0D32B2" fill="#fff9e6" class=" stroke-B1" style="stroke-width:2;" /></g><text x="70.000000" y="653.000000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Browser / iOS App</text></g><g class="aW5pdA=="><g class="shape" ><rect x="2344.000000" y="56.000000" width="265.000000" height="284.000000" stroke="#0D32B2" fill="#f5f5f5" class=" stroke-B2" style="stroke-width:2;stroke-dasharray:8.000000,7.892511;" /></g><text x="2476.500000" y="43.000000" fill="#0A0F25" class="text fill-N1" style="text-anchor:middle;font-size:28px">Init containers</text></g><g class="c3RvcmFnZQ=="><g class="shape" ><rect x="3258.000000" y="526.000000" width="275.000000" height="1042.000000" stroke="#0D32B2" fill="#eaf7ea" class=" stroke-B1" style="stroke-width:2;" /></g><text x="3395.500000" y="513.000000" fill="#0A0F25" class="text fill-N1" style="text-anchor:middle;font-size:28px">Storage</text></g><g class="YXBw"><g class="shape" ><rect x="631.000000" y="467.000000" width="1990.000000" height="1075.000000" stroke="#0D32B2" fill="#eef3ff" class=" stroke-B1" style="stroke-width:2;" /></g><text x="1626.000000" y="454.000000" fill="#0A0F25" class="text fill-N1" style="text-anchor:middle;font-size:28px">Application</text></g><g class="b3Bz"><g class="shape" ><rect x="659.000000" y="1900.000000" width="280.000000" height="206.000000" stroke="#0D32B2" fill="#fef9ec" class=" stroke-B1" style="stroke-width:2;" /></g><text x="799.000000" y="1887.000000" fill="#0A0F25" class="text fill-N1" style="text-anchor:middle;font-size:28px">Ops</text></g><g class="aW5pdC5taW5pby1pbml0"><g class="shape" ><rect x="2383.000000" y="86.000000" width="188.000000" height="82.000000" stroke="#0D32B2" fill="#EDF0FD" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="2477.000000" y="124.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="2477.000000" dy="0.000000">minio-init</tspan><tspan x="2477.000000" dy="18.500000">(mc: create buckets)</tspan></text></g><g class="aW5pdC5wYi1pbml0"><g class="shape" ><rect x="2374.000000" y="228.000000" width="205.000000" height="82.000000" stroke="#0D32B2" fill="#EDF0FD" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="2476.500000" y="266.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="2476.500000" dy="0.000000">pb-init</tspan><tspan x="2476.500000" dy="18.500000">(bootstrap collections)</tspan></text></g><g class="c3RvcmFnZS5taW5pbw=="><g class="shape" ><path d="M 3307 580 C 3307 556 3387 556 3396 556 C 3404 556 3484 556 3484 580 V 746 C 3484 770 3404 770 3396 770 C 3387 770 3307 770 3307 746 V 580 Z" stroke="#0D32B2" fill="#F7F8FE" class=" stroke-B1 fill-AA5" style="stroke-width:2;" /><path d="M 3307 580 C 3307 604 3387 604 3396 604 C 3404 604 3484 604 3484 580" stroke="#0D32B2" fill="#F7F8FE" class=" stroke-B1 fill-AA5" style="stroke-width:2;" /></g><text x="3395.500000" y="632.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="3395.500000" dy="0.000000">MinIO :9000</tspan><tspan x="3395.500000" dy="16.714286"> </tspan><tspan x="3395.500000" dy="16.714286">buckets:</tspan><tspan x="3395.500000" dy="16.714286"> libnovel-chapters</tspan><tspan x="3395.500000" dy="16.714286"> libnovel-audio</tspan><tspan x="3395.500000" dy="16.714286"> avatars</tspan><tspan x="3395.500000" dy="16.714286"> libnovel-browse</tspan></text></g><g class="c3RvcmFnZS5wb2NrZXRiYXNl"><g class="shape" ><path d="M 3288 1080 C 3288 1056 3385 1056 3396 1056 C 3406 1056 3503 1056 3503 1080 V 1246 C 3503 1270 3406 1270 3396 1270 C 3385 1270 3288 1270 3288 1246 V 1080 Z" stroke="#0D32B2" fill="#F7F8FE" class=" stroke-B1 fill-AA5" style="stroke-width:2;" /><path d="M 3288 1080 C 3288 1104 3385 1104 3396 1104 C 3406 1104 3503 1104 3503 1080" stroke="#0D32B2" fill="#F7F8FE" class=" stroke-B1 fill-AA5" style="stroke-width:2;" /></g><text x="3395.500000" y="1132.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="3395.500000" dy="0.000000">PocketBase :8090</tspan><tspan x="3395.500000" dy="16.714286"> </tspan><tspan x="3395.500000" dy="16.714286">collections:</tspan><tspan x="3395.500000" dy="16.714286"> books chapters_idx</tspan><tspan x="3395.500000" dy="16.714286"> audio_cache progress</tspan><tspan x="3395.500000" dy="16.714286"> scrape_jobs app_users</tspan><tspan x="3395.500000" dy="16.714286"> ranking</tspan></text></g><g class="c3RvcmFnZS52YWxrZXk="><g class="shape" ><path d="M 3305 854 C 3305 830 3387 830 3396 830 C 3405 830 3487 830 3487 854 V 972 C 3487 996 3405 996 3396 996 C 3387 996 3305 996 3305 972 V 854 Z" stroke="#0D32B2" fill="#F7F8FE" class=" stroke-B1 fill-AA5" style="stroke-width:2;" /><path d="M 3305 854 C 3305 878 3387 878 3396 878 C 3405 878 3487 878 3487 854" stroke="#0D32B2" fill="#F7F8FE" class=" stroke-B1 fill-AA5" style="stroke-width:2;" /></g><text x="3396.000000" y="906.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="3396.000000" dy="0.000000">Valkey :6379</tspan><tspan x="3396.000000" dy="17.250000"> </tspan><tspan x="3396.000000" dy="17.250000">(presign URL cache</tspan><tspan x="3396.000000" dy="17.250000">TTL-based, shared)</tspan></text></g><g class="c3RvcmFnZS5tZWlsaXNlYXJjaA=="><g class="shape" ><path d="M 3312 1396 C 3312 1372 3388 1372 3396 1372 C 3404 1372 3480 1372 3480 1396 V 1514 C 3480 1538 3404 1538 3396 1538 C 3388 1538 3312 1538 3312 1514 V 1396 Z" stroke="#0D32B2" fill="#F7F8FE" class=" stroke-B1 fill-AA5" style="stroke-width:2;" /><path d="M 3312 1396 C 3312 1420 3388 1420 3396 1420 C 3404 1420 3480 1420 3480 1396" stroke="#0D32B2" fill="#F7F8FE" class=" stroke-B1 fill-AA5" style="stroke-width:2;" /></g><text x="3396.000000" y="1448.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="3396.000000" dy="0.000000">Meilisearch :7700</tspan><tspan x="3396.000000" dy="17.250000"> </tspan><tspan x="3396.000000" dy="17.250000">indices:</tspan><tspan x="3396.000000" dy="17.250000"> books</tspan></text></g><g class="YXBwLmNhZGR5"><g class="shape" ><rect x="661.000000" y="497.000000" width="276.000000" height="178.000000" stroke="#0D32B2" fill="#EDF0FD" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="799.000000" y="535.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="799.000000" dy="0.000000">Caddy :443 / :80</tspan><tspan x="799.000000" dy="16.625000">custom build + caddy-ratelimit</tspan><tspan x="799.000000" dy="16.625000"> </tspan><tspan x="799.000000" dy="16.625000">features:</tspan><tspan x="799.000000" dy="16.625000"> auto-HTTPS (Let&#39;s Encrypt)</tspan><tspan x="799.000000" dy="16.625000"> security headers</tspan><tspan x="799.000000" dy="16.625000"> rate limiting (per-IP)</tspan><tspan x="799.000000" dy="16.625000"> static error pages (502/503/504)</tspan></text></g><g class="YXBwLmJhY2tlbmQ="><g class="shape" ><rect x="2375.000000" y="969.000000" width="204.000000" height="82.000000" stroke="#0D32B2" fill="#EDF0FD" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="2477.000000" y="1007.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="2477.000000" dy="0.000000">Backend API :8080</tspan><tspan x="2477.000000" dy="18.500000">(Go — HTTP API server)</tspan></text></g><g class="YXBwLnJ1bm5lcg=="><g class="shape" ><rect x="2363.000000" y="1398.000000" width="228.000000" height="114.000000" stroke="#0D32B2" fill="#EDF0FD" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="2477.000000" y="1436.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="2477.000000" dy="0.000000">Runner :9091</tspan><tspan x="2477.000000" dy="17.250000">(Go — background worker</tspan><tspan x="2477.000000" dy="17.250000">scraping + TTS jobs</tspan><tspan x="2477.000000" dy="17.250000">/metrics endpoint)</tspan></text></g><g class="YXBwLnVp"><g class="shape" ><rect x="1544.000000" y="1021.000000" width="170.000000" height="82.000000" stroke="#0D32B2" fill="#EDF0FD" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="1629.000000" y="1059.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="1629.000000" dy="0.000000">SvelteKit UI :3000</tspan><tspan x="1629.000000" dy="18.500000">(adapter-node)</tspan></text></g><g class="b3BzLndhdGNodG93ZXI="><g class="shape" ><rect x="689.000000" y="1930.000000" width="220.000000" height="146.000000" stroke="#0D32B2" fill="#EDF0FD" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="799.000000" y="1968.500000" fill="#0A0F25" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px"><tspan x="799.000000" dy="0.000000">Watchtower</tspan><tspan x="799.000000" dy="16.833333">(containrrr/watchtower)</tspan><tspan x="799.000000" dy="16.833333"> </tspan><tspan x="799.000000" dy="16.833333">polls every 5 min</tspan><tspan x="799.000000" dy="16.833333">autopulls + redeploys:</tspan><tspan x="799.000000" dy="16.833333"> backend · runner · ui</tspan></text></g><g class="KGluaXQubWluaW8taW5pdCAtJmd0OyBzdG9yYWdlLm1pbmlvKVswXQ=="><marker id="mk-d2-271920619-2177206569" markerWidth="10.000000" markerHeight="12.000000" refX="7.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" fill="#0D32B2" class="connection fill-B2" stroke-width="2" /> </marker><path d="M 2573.500000 127.000000 C 2692.699951 127.000000 2765.699951 127.000000 2829.750000 127.000000 C 2893.800049 127.000000 3188.800049 213.600006 3342.364503 556.349637" stroke="#0D32B2" fill="none" class="connection stroke-B2" style="stroke-width:2;stroke-dasharray:8.000000,7.892511;" marker-end="url(#mk-d2-271920619-2177206569)" mask="url(#d2-271920619)" /><text x="3068.500000" y="184.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">create buckets</text></g><g class="KGluaXQucGItaW5pdCAtJmd0OyBzdG9yYWdlLnBvY2tldGJhc2UpWzBd"><path d="M 2581.000000 269.000000 C 2694.199951 269.000000 2765.699951 269.000000 2829.750000 269.000000 C 2893.800049 269.000000 3192.800049 426.600006 3362.951676 1053.139816" stroke="#0D32B2" fill="none" class="connection stroke-B2" style="stroke-width:2;stroke-dasharray:8.000000,7.892511;" marker-end="url(#mk-d2-271920619-2177206569)" mask="url(#d2-271920619)" /><text x="3192.500000" y="432.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">bootstrap schema</text></g><g class="KGFwcC5iYWNrZW5kIC0mZ3Q7IHN0b3JhZ2UubWluaW8pWzBd"><marker id="mk-d2-271920619-3488378134" markerWidth="10.000000" markerHeight="12.000000" refX="7.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" fill="#0D32B2" class="connection fill-B1" stroke-width="2" /> </marker><path d="M 2559.135810 967.845454 C 2689.870117 901.549988 2765.699951 884.750000 2829.750000 884.750000 C 2893.800049 884.750000 3181.399902 856.400024 3304.031058 745.680556" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2945.500000" y="877.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="2945.500000" dy="0.000000">blobs (chapters, audio,</tspan><tspan x="2945.500000" dy="18.500000">avatars, browse)</tspan></text></g><g class="KGFwcC5iYWNrZW5kIC0mZ3Q7IHN0b3JhZ2UucG9ja2V0YmFzZSlbMF0="><path d="M 2581.427031 981.076694 C 2694.300049 949.721985 2765.699951 941.750000 2829.750000 941.750000 C 2893.800049 941.750000 3178.600098 967.599976 3290.032507 1068.317840" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2954.500000" y="945.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="2954.500000" dy="0.000000">structured records</tspan><tspan x="2954.500000" dy="18.500000">(books, progress, jobs…)</tspan></text></g><g class="KGFwcC5iYWNrZW5kIC0mZ3Q7IHN0b3JhZ2UudmFsa2V5KVswXQ=="><path d="M 2581.447891 1033.789622 C 2694.300049 1060.067017 2765.699951 1066.750000 2829.750000 1066.750000 C 2893.800049 1066.750000 3181.000000 1047.400024 3301.606778 972.118028" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2952.000000" y="1060.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="2952.000000" dy="0.000000">cache presigned URLs</tspan><tspan x="2952.000000" dy="18.500000">(SET/GET with TTL)</tspan></text></g><g class="KGFwcC5ydW5uZXIgLSZndDsgc3RvcmFnZS5taW5pbylbMF0="><path d="M 2547.865162 1396.235151 C 2687.663086 1282.099976 2765.699951 1253.250000 2829.750000 1253.250000 C 2893.800049 1253.250000 3190.399902 1156.199951 3350.462753 771.692814" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="3055.000000" y="1198.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="3055.000000" dy="0.000000">write chapter markdown</tspan><tspan x="3055.000000" dy="18.500000">&amp; audio MP3s</tspan></text></g><g class="KGFwcC5ydW5uZXIgLSZndDsgc3RvcmFnZS5wb2NrZXRiYXNlKVswXQ=="><path d="M 2575.629235 1396.489863 C 2693.179932 1327.699951 2765.699951 1310.250000 2829.750000 1310.250000 C 2893.800049 1310.250000 3177.600098 1293.599976 3284.574966 1229.066190" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2929.500000" y="1306.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="2929.500000" dy="0.000000">read/update scrape jobs</tspan><tspan x="2929.500000" dy="18.500000">write book records</tspan></text></g><g class="KGFwcC5ydW5uZXIgLSZndDsgc3RvcmFnZS5tZWlsaXNlYXJjaClbMF0="><path d="M 2593.500000 1454.500000 C 2696.699951 1454.500000 2765.699951 1454.500000 2829.750000 1454.500000 C 2893.800049 1454.500000 3182.399902 1454.400024 3308.000019 1454.012346" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2952.000000" y="1452.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="2952.000000" dy="0.000000">index books on</tspan><tspan x="2952.000000" dy="18.500000">scrape completion</tspan></text></g><g class="KGFwcC51aSAtJmd0OyBzdG9yYWdlLnZhbGtleSlbMF0="><path d="M 1680.445327 1019.230338 C 1923.780029 819.299988 2034.000000 769.000000 2107.500000 769.000000 C 2181.000000 769.000000 2279.300049 769.000000 2353.250000 769.000000 C 2427.199951 769.000000 2525.800049 769.000000 2599.750000 769.000000 C 2673.699951 769.000000 2765.699951 769.000000 2829.750000 769.000000 C 2893.800049 769.000000 3181.000000 787.200012 3301.550548 857.974838" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2460.500000" y="775.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">read presigned URL cache</text></g><g class="KGFwcC51aSAtJmd0OyBzdG9yYWdlLnBvY2tldGJhc2UpWzBd"><path d="M 1715.843527 1097.775505 C 1930.800049 1188.199951 2034.000000 1211.000000 2107.500000 1211.000000 C 2181.000000 1211.000000 2279.300049 1211.000000 2353.250000 1211.000000 C 2427.199951 1211.000000 2525.800049 1211.000000 2599.750000 1211.000000 C 2673.699951 1211.000000 2765.699951 1211.000000 2829.750000 1211.000000 C 2893.800049 1211.000000 3177.600098 1205.599976 3284.074429 1184.768046" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2492.000000" y="1209.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="2492.000000" dy="0.000000">auth, progress,</tspan><tspan x="2492.000000" dy="18.500000">comments, settings</tspan></text></g><g class="YXBwLih1aSAtJmd0OyBiYWNrZW5kKVswXQ=="><path d="M 1706.222195 1104.462438 C 1928.892944 1226.699951 2271.000000 1216.099976 2432.185336 1053.342124" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2088.500000" y="1211.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="2088.500000" dy="0.000000">REST API calls (server-side)</tspan><tspan x="2088.500000" dy="17.666667">/api/catalogue /api/book-preview</tspan><tspan x="2088.500000" dy="17.666667">/api/chapter-text /api/audio etc.</tspan></text></g><g class="YXBwLihjYWRkeSAtJmd0OyB1aSlbMF0="><path d="M 939.421054 545.277610 C 1042.699951 515.366028 1355.630981 610.299988 1602.086326 1017.078920" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="1367.000000" y="610.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="1367.000000" dy="0.000000">/* (catch-all)</tspan><tspan x="1367.000000" dy="17.250000">/api/scrape/*</tspan><tspan x="1367.000000" dy="17.250000">/api/chapter-text-preview/*</tspan><tspan x="1367.000000" dy="17.250000">→ SvelteKit (auth enforced)</tspan></text></g><g class="YXBwLihjYWRkeSAtJmd0OyBiYWNrZW5kKVswXQ=="><path d="M 939.492541 573.465433 C 1042.699951 564.526978 1113.900024 562.250000 1181.250000 562.250000 C 1248.599976 562.250000 1360.599976 562.250000 1461.250000 562.250000 C 1561.900024 562.250000 1700.199951 562.250000 1807.000000 562.250000 C 1913.800049 562.250000 2274.782959 643.549988 2451.985114 965.246375" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="1796.000000" y="536.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="1796.000000" dy="0.000000">/health /scrape*</tspan><tspan x="1796.000000" dy="17.000000">/api/browse /api/book-preview/*</tspan><tspan x="1796.000000" dy="17.000000">/api/chapter-text/*</tspan><tspan x="1796.000000" dy="17.000000">/api/reindex/* /api/cover/*</tspan><tspan x="1796.000000" dy="17.000000">/api/audio-proxy/*</tspan></text></g><g class="KGFwcC5jYWRkeSAtJmd0OyBzdG9yYWdlLm1pbmlvKVswXQ=="><path d="M 939.478963 605.813307 C 1042.699951 620.903992 1113.900024 624.750000 1181.250000 624.750000 C 1248.599976 624.750000 1360.599976 624.750000 1461.250000 624.750000 C 1561.900024 624.750000 1700.199951 624.750000 1807.000000 624.750000 C 1913.800049 624.750000 2034.000000 624.750000 2107.500000 624.750000 C 2181.000000 624.750000 2279.300049 624.750000 2353.250000 624.750000 C 2427.199951 624.750000 2525.800049 624.750000 2599.750000 624.750000 C 2673.699951 624.750000 2765.699951 624.750000 2829.750000 624.750000 C 2893.800049 624.750000 3181.399902 629.799988 3303.050749 649.364850" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2122.000000" y="622.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="2122.000000" dy="0.000000">/avatars/*</tspan><tspan x="2122.000000" dy="18.500000">(presigned avatar GETs)</tspan></text></g><g class="KGFwcC5ydW5uZXIgLSZndDsgbm92ZWxmaXJlKVswXQ=="><path d="M 2547.577498 1513.777973 C 2687.606934 1630.099976 2765.699951 1659.500000 2829.750000 1659.500000 C 2893.800049 1659.500000 3183.600098 1659.599976 3314.000018 1659.988095" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2908.000000" y="1657.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="2908.000000" dy="0.000000">scrape</tspan><tspan x="2908.000000" dy="18.500000">(HTTP GET)</tspan></text></g><g class="KGFwcC5ydW5uZXIgLSZndDsga29rb3JvKVswXQ=="><path d="M 2517.915497 1514.131745 C 2681.750977 1745.300049 2765.699951 1803.500000 2829.750000 1803.500000 C 2893.800049 1803.500000 3178.000000 1803.599976 3286.000026 1803.985714" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="2834.500000" y="1801.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="2834.500000" dy="0.000000">TTS generation</tspan><tspan x="2834.500000" dy="18.500000">(HTTP POST)</tspan></text></g><g class="KGFwcC5jYWRkeSAtJmd0OyBsZXRzZW5jcnlwdClbMF0="><path d="M 862.430426 677.132497 C 1027.454956 910.299988 1356.000000 841.200012 1604.242706 333.593316" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="1329.500000" y="844.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="1329.500000" dy="0.000000">ACME certificate</tspan><tspan x="1329.500000" dy="18.500000">(TLS-ALPN-01)</tspan></text></g><g class="KG9wcy53YXRjaHRvd2VyIC0mZ3Q7IGFwcC5iYWNrZW5kKVswXQ=="><path d="M 911.470733 1983.249069 C 1037.098999 1961.517944 1113.900024 1830.099976 1181.250000 1641.250000 C 1248.599976 1452.400024 1360.599976 1326.500000 1461.250000 1326.500000 C 1561.900024 1326.500000 1700.199951 1326.500000 1807.000000 1326.500000 C 1913.800049 1326.500000 2272.800049 1271.300049 2441.548999 1053.661106" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="1532.500000" y="1332.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">watch (label-enabled)</text></g><g class="KG9wcy53YXRjaHRvd2VyIC0mZ3Q7IGFwcC5ydW5uZXIpWzBd"><path d="M 911.500000 2002.500000 C 1037.098999 2002.500000 1113.900024 1892.900024 1181.250000 1728.500000 C 1248.599976 1564.099976 1360.599976 1454.500000 1461.250000 1454.500000 C 1561.900024 1454.500000 1700.199951 1454.500000 1807.000000 1454.500000 C 1913.800049 1454.500000 2256.500000 1454.500000 2358.500000 1454.500000" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="1474.500000" y="1460.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">watch (label-enabled)</text></g><g class="KG9wcy53YXRjaHRvd2VyIC0mZ3Q7IGFwcC51aSlbMF0="><path d="M 911.457232 2025.886365 C 1037.098999 2052.294922 1356.699951 1640.599976 1607.797849 1106.619763" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="1339.500000" y="1669.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">watch (label-enabled)</text></g><g class="KGJyb3dzZXIgLSZndDsgYXBwLmNhZGR5KVswXQ=="><path d="M 115.999995 585.995454 C 290.000000 585.599976 554.500000 585.500000 656.500000 585.500000" stroke="#0D32B2" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-271920619-3488378134)" mask="url(#d2-271920619)" /><text x="387.500000" y="583.000000" fill="#676C7E" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px"><tspan x="387.500000" dy="0.000000">HTTPS :443</tspan><tspan x="387.500000" dy="18.500000">(single entry point)</tspan></text></g><mask id="d2-271920619" maskUnits="userSpaceOnUse" x="-101" y="-85" width="3735" height="2292">
<rect x="-101" y="-85" width="3735" height="2292" fill="white"></rect>
<rect x="3018.000000" y="168.000000" width="101" height="21" fill="black"></rect>
<rect x="3131.000000" y="416.000000" width="123" height="21" fill="black"></rect>
<rect x="2869.000000" y="861.000000" width="153" height="37" fill="black"></rect>
<rect x="2874.000000" y="929.000000" width="161" height="37" fill="black"></rect>
<rect x="2878.000000" y="1044.000000" width="148" height="37" fill="black"></rect>
<rect x="2972.000000" y="1182.000000" width="166" height="37" fill="black"></rect>
<rect x="2847.000000" y="1290.000000" width="165" height="37" fill="black"></rect>
<rect x="2889.000000" y="1436.000000" width="126" height="37" fill="black"></rect>
<rect x="2373.000000" y="759.000000" width="175" height="21" fill="black"></rect>
<rect x="2426.000000" y="1193.000000" width="132" height="37" fill="black"></rect>
<rect x="1974.000000" y="1195.000000" width="229" height="53" fill="black"></rect>
<rect x="1273.000000" y="594.000000" width="188" height="69" fill="black"></rect>
<rect x="1683.000000" y="520.000000" width="226" height="85" fill="black"></rect>
<rect x="2041.000000" y="606.000000" width="162" height="37" fill="black"></rect>
<rect x="2869.000000" y="1641.000000" width="78" height="37" fill="black"></rect>
<rect x="2783.000000" y="1785.000000" width="103" height="37" fill="black"></rect>
<rect x="1274.000000" y="828.000000" width="111" height="37" fill="black"></rect>
<rect x="1459.000000" y="1316.000000" width="147" height="21" fill="black"></rect>
<rect x="1401.000000" y="1444.000000" width="147" height="21" fill="black"></rect>
<rect x="1266.000000" y="1653.000000" width="147" height="21" fill="black"></rect>
<rect x="324.000000" y="567.000000" width="127" height="37" fill="black"></rect>
</mask></svg></svg>