@itsthecsguy/linework 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +11 -0
  3. package/README.md +164 -2
  4. package/assets/drawio/LICENSE +201 -0
  5. package/assets/drawio/VERSION +1 -0
  6. package/assets/drawio/favicon.ico +0 -0
  7. package/assets/drawio/images/1x1.png +0 -0
  8. package/assets/drawio/images/2x2.png +0 -0
  9. package/assets/drawio/images/3x3.png +0 -0
  10. package/assets/drawio/images/ajax-loader.gif +0 -0
  11. package/assets/drawio/images/android-chrome-512x512.png +0 -0
  12. package/assets/drawio/images/apple-touch-icon.png +0 -0
  13. package/assets/drawio/images/aui-wait.gif +0 -0
  14. package/assets/drawio/images/broken.png +0 -0
  15. package/assets/drawio/images/browserconfig.xml +9 -0
  16. package/assets/drawio/images/close.png +0 -0
  17. package/assets/drawio/images/cloud-connector-atlas.png +0 -0
  18. package/assets/drawio/images/collapsed.gif +0 -0
  19. package/assets/drawio/images/delete.png +0 -0
  20. package/assets/drawio/images/document-google-drive-icon-80.png +0 -0
  21. package/assets/drawio/images/draw-search.png +0 -0
  22. package/assets/drawio/images/drawio.svg +19 -0
  23. package/assets/drawio/images/drawlogo-color.svg +50 -0
  24. package/assets/drawio/images/drawlogo-gray.svg +18 -0
  25. package/assets/drawio/images/drawlogo-text-bottom.svg +75 -0
  26. package/assets/drawio/images/drawlogo.svg +18 -0
  27. package/assets/drawio/images/drawlogo128.png +0 -0
  28. package/assets/drawio/images/drawlogo144.png +0 -0
  29. package/assets/drawio/images/drawlogo256.png +0 -0
  30. package/assets/drawio/images/drawlogo48-gray.png +0 -0
  31. package/assets/drawio/images/drawlogo48.png +0 -0
  32. package/assets/drawio/images/drawlogo80.png +0 -0
  33. package/assets/drawio/images/droptarget.png +0 -0
  34. package/assets/drawio/images/edit.gif +0 -0
  35. package/assets/drawio/images/edit16.png +0 -0
  36. package/assets/drawio/images/edit32.png +0 -0
  37. package/assets/drawio/images/edit80.png +0 -0
  38. package/assets/drawio/images/embed-icon.png +0 -0
  39. package/assets/drawio/images/expanded.gif +0 -0
  40. package/assets/drawio/images/facebook.png +0 -0
  41. package/assets/drawio/images/favicon-16x16.png +0 -0
  42. package/assets/drawio/images/favicon-32x32.png +0 -0
  43. package/assets/drawio/images/file.png +0 -0
  44. package/assets/drawio/images/folder.png +0 -0
  45. package/assets/drawio/images/gadget-screenshot.png +0 -0
  46. package/assets/drawio/images/gadget-thumb.png +0 -0
  47. package/assets/drawio/images/github-logo-white.svg +6 -0
  48. package/assets/drawio/images/github-logo.svg +17 -0
  49. package/assets/drawio/images/gitlab-logo-white.svg +1 -0
  50. package/assets/drawio/images/gitlab-logo.svg +1 -0
  51. package/assets/drawio/images/glyphicons_blogger.png +0 -0
  52. package/assets/drawio/images/glyphicons_facebook.png +0 -0
  53. package/assets/drawio/images/glyphicons_github.png +0 -0
  54. package/assets/drawio/images/glyphicons_google.png +0 -0
  55. package/assets/drawio/images/glyphicons_star.png +0 -0
  56. package/assets/drawio/images/glyphicons_twitter.png +0 -0
  57. package/assets/drawio/images/glyphicons_youtube.png +0 -0
  58. package/assets/drawio/images/google-drive-connector-atlas.png +0 -0
  59. package/assets/drawio/images/google-drive-connector-atlas.svg +121 -0
  60. package/assets/drawio/images/google-drive-logo-white.svg +9 -0
  61. package/assets/drawio/images/google-drive-logo.svg +17 -0
  62. package/assets/drawio/images/google-share.png +0 -0
  63. package/assets/drawio/images/icon-192-maskable.png +0 -0
  64. package/assets/drawio/images/icon-192.png +0 -0
  65. package/assets/drawio/images/icon-512-maskable.png +0 -0
  66. package/assets/drawio/images/icon-512.png +0 -0
  67. package/assets/drawio/images/icon-search.svg +21 -0
  68. package/assets/drawio/images/img-hi-res.png +0 -0
  69. package/assets/drawio/images/img-lo-res.png +0 -0
  70. package/assets/drawio/images/list.svg +16 -0
  71. package/assets/drawio/images/locked.png +0 -0
  72. package/assets/drawio/images/log.png +0 -0
  73. package/assets/drawio/images/logo-confluence.png +0 -0
  74. package/assets/drawio/images/logo-flat-small.png +0 -0
  75. package/assets/drawio/images/logo-flat.png +0 -0
  76. package/assets/drawio/images/logo-jira.png +0 -0
  77. package/assets/drawio/images/logo-small.gif +0 -0
  78. package/assets/drawio/images/logo-white.png +0 -0
  79. package/assets/drawio/images/logo.png +0 -0
  80. package/assets/drawio/images/manifest.json +25 -0
  81. package/assets/drawio/images/move.png +0 -0
  82. package/assets/drawio/images/notion-logo-white.svg +1 -0
  83. package/assets/drawio/images/notion-logo.svg +1 -0
  84. package/assets/drawio/images/onedrive-connector-atlas.png +0 -0
  85. package/assets/drawio/images/onedrive-connector-atlas.svg +248 -0
  86. package/assets/drawio/images/onedrive-logo-white.svg +29 -0
  87. package/assets/drawio/images/onedrive-logo.svg +29 -0
  88. package/assets/drawio/images/osa_database.png +0 -0
  89. package/assets/drawio/images/osa_drive-harddisk.png +0 -0
  90. package/assets/drawio/images/plant-uml-atlas.png +0 -0
  91. package/assets/drawio/images/samepage-icon-color.svg +37 -0
  92. package/assets/drawio/images/save.png +0 -0
  93. package/assets/drawio/images/sidebar-android.png +0 -0
  94. package/assets/drawio/images/sidebar-archimate.png +0 -0
  95. package/assets/drawio/images/sidebar-arrows.png +0 -0
  96. package/assets/drawio/images/sidebar-arrows2.png +0 -0
  97. package/assets/drawio/images/sidebar-basic.png +0 -0
  98. package/assets/drawio/images/sidebar-c4.png +0 -0
  99. package/assets/drawio/images/sidebar-cabinets.png +0 -0
  100. package/assets/drawio/images/sidebar-cumulus.png +0 -0
  101. package/assets/drawio/images/sidebar-dfd.png +0 -0
  102. package/assets/drawio/images/sidebar-dynamics365.png +0 -0
  103. package/assets/drawio/images/sidebar-eip.png +0 -0
  104. package/assets/drawio/images/sidebar-er.png +0 -0
  105. package/assets/drawio/images/sidebar-floorplans.png +0 -0
  106. package/assets/drawio/images/sidebar-flowchart.png +0 -0
  107. package/assets/drawio/images/sidebar-gcp3.png +0 -0
  108. package/assets/drawio/images/sidebar-general.png +0 -0
  109. package/assets/drawio/images/sidebar-kubernetes.png +0 -0
  110. package/assets/drawio/images/sidebar-leanmapping.png +0 -0
  111. package/assets/drawio/images/sidebar-mockups.png +0 -0
  112. package/assets/drawio/images/sidebar-network.png +0 -0
  113. package/assets/drawio/images/sidebar-network2.png +0 -0
  114. package/assets/drawio/images/sidebar-openstack.png +0 -0
  115. package/assets/drawio/images/sidebar-sitemap.png +0 -0
  116. package/assets/drawio/images/sidebar-threatmodeling.png +0 -0
  117. package/assets/drawio/images/sidebar-uml.png +0 -0
  118. package/assets/drawio/images/sketch-logo128.png +0 -0
  119. package/assets/drawio/images/spin.gif +0 -0
  120. package/assets/drawio/images/sprites.png +0 -0
  121. package/assets/drawio/images/stop-flat-icon-80.png +0 -0
  122. package/assets/drawio/images/submenu.gif +0 -0
  123. package/assets/drawio/images/touch-submenu.png +0 -0
  124. package/assets/drawio/images/transparent.gif +0 -0
  125. package/assets/drawio/images/trello-logo-white-orange.svg +6 -0
  126. package/assets/drawio/images/trello-logo-white.svg +6 -0
  127. package/assets/drawio/images/trello-logo.svg +1 -0
  128. package/assets/drawio/images/tweet.png +0 -0
  129. package/assets/drawio/images/update16.png +0 -0
  130. package/assets/drawio/images/update32.png +0 -0
  131. package/assets/drawio/images/update80.png +0 -0
  132. package/assets/drawio/images/youtube.png +0 -0
  133. package/assets/drawio/img/clipart/Battery_0_128x128.png +0 -0
  134. package/assets/drawio/img/clipart/Battery_100_128x128.png +0 -0
  135. package/assets/drawio/img/clipart/Battery_50_128x128.png +0 -0
  136. package/assets/drawio/img/clipart/Battery_75_128x128.png +0 -0
  137. package/assets/drawio/img/clipart/Battery_allstates_128x128.png +0 -0
  138. package/assets/drawio/img/clipart/Bluetooth_128x128.png +0 -0
  139. package/assets/drawio/img/clipart/Earth_globe_128x128.png +0 -0
  140. package/assets/drawio/img/clipart/Empty_Folder_128x128.png +0 -0
  141. package/assets/drawio/img/clipart/Full_Folder_128x128.png +0 -0
  142. package/assets/drawio/img/clipart/Gear_128x128.png +0 -0
  143. package/assets/drawio/img/clipart/Keys_128x128.png +0 -0
  144. package/assets/drawio/img/clipart/Lock_128x128.png +0 -0
  145. package/assets/drawio/img/clipart/Mouse_Pointer_128x128.png +0 -0
  146. package/assets/drawio/img/clipart/Plug_128x128.png +0 -0
  147. package/assets/drawio/img/clipart/Ships_Wheel_128x128.png +0 -0
  148. package/assets/drawio/img/clipart/Star_128x128.png +0 -0
  149. package/assets/drawio/img/clipart/Tire_128x128.png +0 -0
  150. package/assets/drawio/index.html +92 -0
  151. package/assets/drawio/js/PostConfig.js +7 -0
  152. package/assets/drawio/js/PreConfig.js +13 -0
  153. package/assets/drawio/js/app.min.js +18466 -0
  154. package/assets/drawio/js/bootstrap.js +428 -0
  155. package/assets/drawio/js/diagramly/LibavoidRouting.js +4459 -0
  156. package/assets/drawio/js/export-init.js +21 -0
  157. package/assets/drawio/js/extensions.min.js +10478 -0
  158. package/assets/drawio/js/libavoid-js/LICENSE +505 -0
  159. package/assets/drawio/js/libavoid-js/libavoid-routing.js +1633 -0
  160. package/assets/drawio/js/libavoid-js/libavoid.min.js +59 -0
  161. package/assets/drawio/js/main.js +22 -0
  162. package/assets/drawio/js/rough/rough.min.js +1 -0
  163. package/assets/drawio/js/shapes-14-6-5.min.js +3457 -0
  164. package/assets/drawio/js/stencils.min.js +447 -0
  165. package/assets/drawio/mxgraph/css/common.css +147 -0
  166. package/assets/drawio/resources/dia.txt +2901 -0
  167. package/assets/drawio/styles/dark-default.xml +109 -0
  168. package/assets/drawio/styles/default-old.xml +109 -0
  169. package/assets/drawio/styles/default.xml +203 -0
  170. package/assets/drawio/styles/fonts/ArchitectsDaughter-Regular.ttf +0 -0
  171. package/assets/drawio/styles/grapheditor.css +4501 -0
  172. package/assets/drawio/styles/high-contrast.css +128 -0
  173. package/assets/drawio/styles/thumb_horz.png +0 -0
  174. package/assets/drawio/styles/thumb_vertical.png +0 -0
  175. package/assets/fonts/ibm-plex-mono-LICENSE.txt +93 -0
  176. package/assets/fonts/ibm-plex-sans-LICENSE.txt +93 -0
  177. package/assets/fonts/kalam-400.woff2 +0 -0
  178. package/assets/fonts/kalam-700.woff2 +0 -0
  179. package/assets/fonts/kalam-LICENSE.txt +93 -0
  180. package/assets/fonts/plex-mono-400.woff2 +0 -0
  181. package/assets/fonts/plex-mono-600.woff2 +0 -0
  182. package/assets/fonts/plex-sans-400.woff2 +0 -0
  183. package/assets/fonts/plex-sans-600.woff2 +0 -0
  184. package/dist/api.js +181 -0
  185. package/dist/cli.js +262 -0
  186. package/dist/drawio/icons.js +121 -0
  187. package/dist/drawio/merge.js +309 -0
  188. package/dist/drawio/read.js +180 -0
  189. package/dist/drawio/show.js +501 -0
  190. package/dist/drawio/theme.js +425 -0
  191. package/dist/drawio/write.js +300 -0
  192. package/dist/edit/server.js +212 -0
  193. package/dist/git.js +46 -0
  194. package/dist/import/mermaid.js +569 -0
  195. package/dist/layout/layout.js +212 -0
  196. package/dist/layout/sequence.js +333 -0
  197. package/dist/layout/text.js +73 -0
  198. package/dist/lint/check.js +184 -0
  199. package/dist/lint/fixlabels.js +128 -0
  200. package/dist/mcp/server.js +239 -0
  201. package/dist/publish.js +121 -0
  202. package/dist/render/browser.js +210 -0
  203. package/dist/render/fonts.js +66 -0
  204. package/dist/report.js +36 -0
  205. package/dist/spec/model.js +53 -0
  206. package/dist/spec/parse.js +497 -0
  207. package/package.json +71 -4
  208. package/skills/linework/SKILL.md +214 -0
  209. package/skills/linework/examples/billing-er.drawio.svg +4 -0
  210. package/skills/linework/examples/billing-er.yaml +31 -0
  211. package/skills/linework/examples/checkout.drawio.svg +4 -0
  212. package/skills/linework/examples/checkout.yaml +28 -0
  213. package/skills/linework/examples/pay-sequence.drawio.svg +4 -0
  214. package/skills/linework/examples/pay-sequence.yaml +28 -0
  215. package/skills/linework/examples/payment-state.drawio.svg +4 -0
  216. package/skills/linework/examples/payment-state.yaml +22 -0
  217. package/skills/linework/examples/refund-flow.drawio.svg +4 -0
  218. package/skills/linework/examples/refund-flow.yaml +29 -0
  219. package/skills/linework/examples/serverless-aws.drawio.svg +4 -0
  220. package/skills/linework/examples/serverless-aws.yaml +23 -0
  221. package/skills/linework/references/google-docs.md +46 -0
  222. package/skills/linework/references/spec.md +312 -0
  223. package/skills/linework/references/style-guide.md +53 -0
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- Do not edit this file with editors other than draw.io -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg xmlns="http://www.w3.org/2000/svg" style="background: #FFFFFF; background-color: light-dark(#FFFFFF, #121212);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="421px" height="813px" viewBox="0 0 421 813" content="&lt;mxfile host=&quot;aiviz&quot; agent=&quot;aiviz&quot;&gt;&lt;diagram id=&quot;aiviz&quot; name=&quot;Image pipeline&quot;&gt;&lt;mxGraphModel grid=&quot;1&quot; gridSize=&quot;8&quot; guides=&quot;1&quot; tooltips=&quot;1&quot; connect=&quot;1&quot; arrows=&quot;1&quot; page=&quot;0&quot; background=&quot;#FFFFFF&quot; math=&quot;0&quot; shadow=&quot;0&quot;&gt;&lt;root&gt;&lt;object id=&quot;0&quot; label=&quot;&quot; aiviz_version=&quot;1&quot; aiviz_type=&quot;architecture&quot; aiviz_direction=&quot;auto&quot; aiviz_title=&quot;Image pipeline&quot;&gt;&lt;mxCell/&gt;&lt;/object&gt;&lt;mxCell id=&quot;1&quot; parent=&quot;0&quot;/&gt;&lt;object id=&quot;aws&quot; label=&quot;AWS account&quot; aiviz_type=&quot;group&quot; aiviz_label=&quot;AWS account&quot; aiviz_auto=&quot;16,173,375,622&quot;&gt;&lt;mxCell style=&quot;rounded=1;absoluteArcSize=1;arcSize=20;html=1;whiteSpace=wrap;container=1;collapsible=0;fillColor=#F8FAFC;strokeColor=#CBD5E1;strokeWidth=1;dashed=1;dashPattern=4 4;verticalAlign=top;align=left;spacingLeft=14;spacingTop=6;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#64748B;fontStyle=1;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;16&quot; y=&quot;173&quot; width=&quot;375&quot; height=&quot;622&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;user&quot; label=&quot;&amp;lt;span style=&amp;quot;font-weight:600&amp;quot;&amp;gt;Uploader&amp;lt;/span&amp;gt;&quot; aiviz_kind=&quot;person&quot; aiviz_label=&quot;Uploader&quot; aiviz_icon=&quot;aws.users&quot; aiviz_auto=&quot;251,16,152,40&quot;&gt;&lt;mxCell style=&quot;rounded=1;absoluteArcSize=1;arcSize=16;html=1;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=13;fontColor=#0F172A;fillColor=#FDF4FF;strokeColor=#C026D3;strokeWidth=1.5;align=left;spacingLeft=44;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;251&quot; y=&quot;16&quot; width=&quot;152&quot; height=&quot;40&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;api&quot; label=&quot;&amp;lt;span style=&amp;quot;font-weight:600&amp;quot;&amp;gt;Upload API&amp;lt;/span&amp;gt;&quot; aiviz_kind=&quot;service&quot; aiviz_label=&quot;Upload API&quot; aiviz_icon=&quot;aws.api_gateway&quot; aiviz_auto=&quot;192,40,152,40&quot;&gt;&lt;mxCell style=&quot;rounded=1;absoluteArcSize=1;arcSize=16;html=1;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=13;fontColor=#0F172A;fillColor=#EEF2FF;strokeColor=#4F46E5;strokeWidth=1.5;align=left;spacingLeft=44;&quot; vertex=&quot;1&quot; parent=&quot;aws&quot;&gt;&lt;mxGeometry x=&quot;192&quot; y=&quot;40&quot; width=&quot;152&quot; height=&quot;40&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;sign&quot; label=&quot;&amp;lt;span style=&amp;quot;font-weight:600&amp;quot;&amp;gt;Presign&amp;lt;/span&amp;gt;&quot; aiviz_kind=&quot;function&quot; aiviz_label=&quot;Presign&quot; aiviz_icon=&quot;aws.lambda&quot; aiviz_auto=&quot;192,136,152,40&quot;&gt;&lt;mxCell style=&quot;rounded=1;absoluteArcSize=1;arcSize=16;html=1;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=13;fontColor=#0F172A;fillColor=#EEF2FF;strokeColor=#4F46E5;strokeWidth=1.5;dashed=1;dashPattern=6 4;align=left;spacingLeft=44;&quot; vertex=&quot;1&quot; parent=&quot;aws&quot;&gt;&lt;mxGeometry x=&quot;192&quot; y=&quot;136&quot; width=&quot;152&quot; height=&quot;40&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;bucket&quot; label=&quot;&amp;lt;span style=&amp;quot;font-weight:600&amp;quot;&amp;gt;Raw images&amp;lt;/span&amp;gt;&quot; aiviz_kind=&quot;storage&quot; aiviz_label=&quot;Raw images&quot; aiviz_icon=&quot;aws.s3&quot; aiviz_auto=&quot;58,242,152,56&quot;&gt;&lt;mxCell style=&quot;shape=cylinder3;boundedLbl=1;backgroundOutline=1;size=8;html=1;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=13;fontColor=#0F172A;fillColor=#ECFDF5;strokeColor=#059669;strokeWidth=1.5;align=left;spacingLeft=44;&quot; vertex=&quot;1&quot; parent=&quot;aws&quot;&gt;&lt;mxGeometry x=&quot;58&quot; y=&quot;242&quot; width=&quot;152&quot; height=&quot;56&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;queue&quot; label=&quot;&amp;lt;span style=&amp;quot;font-weight:600&amp;quot;&amp;gt;resize-jobs&amp;lt;/span&amp;gt;&quot; aiviz_kind=&quot;queue&quot; aiviz_label=&quot;resize-jobs&quot; aiviz_icon=&quot;aws.sqs&quot; aiviz_auto=&quot;130,354,152,40&quot;&gt;&lt;mxCell style=&quot;rounded=1;arcSize=50;html=1;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=13;fontColor=#0F172A;fillColor=#FFF7ED;strokeColor=#D97706;strokeWidth=1.5;align=left;spacingLeft=44;&quot; vertex=&quot;1&quot; parent=&quot;aws&quot;&gt;&lt;mxGeometry x=&quot;130&quot; y=&quot;354&quot; width=&quot;152&quot; height=&quot;40&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;resize&quot; label=&quot;&amp;lt;span style=&amp;quot;font-weight:600&amp;quot;&amp;gt;Resizer&amp;lt;/span&amp;gt;&quot; aiviz_kind=&quot;function&quot; aiviz_label=&quot;Resizer&quot; aiviz_icon=&quot;aws.lambda&quot; aiviz_auto=&quot;58,450,152,40&quot;&gt;&lt;mxCell style=&quot;rounded=1;absoluteArcSize=1;arcSize=16;html=1;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=13;fontColor=#0F172A;fillColor=#EEF2FF;strokeColor=#4F46E5;strokeWidth=1.5;dashed=1;dashPattern=6 4;align=left;spacingLeft=44;&quot; vertex=&quot;1&quot; parent=&quot;aws&quot;&gt;&lt;mxGeometry x=&quot;58&quot; y=&quot;450&quot; width=&quot;152&quot; height=&quot;40&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;table&quot; label=&quot;&amp;lt;span style=&amp;quot;font-weight:600&amp;quot;&amp;gt;Image index&amp;lt;/span&amp;gt;&quot; aiviz_kind=&quot;database&quot; aiviz_label=&quot;Image index&quot; aiviz_icon=&quot;aws.dynamodb&quot; aiviz_auto=&quot;58,546,152,56&quot;&gt;&lt;mxCell style=&quot;shape=cylinder3;boundedLbl=1;backgroundOutline=1;size=8;html=1;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=13;fontColor=#0F172A;fillColor=#ECFDF5;strokeColor=#059669;strokeWidth=1.5;align=left;spacingLeft=44;&quot; vertex=&quot;1&quot; parent=&quot;aws&quot;&gt;&lt;mxGeometry x=&quot;58&quot; y=&quot;546&quot; width=&quot;152&quot; height=&quot;56&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;cdn&quot; label=&quot;&amp;lt;span style=&amp;quot;font-weight:600&amp;quot;&amp;gt;CDN&amp;lt;/span&amp;gt;&quot; aiviz_kind=&quot;service&quot; aiviz_label=&quot;CDN&quot; aiviz_icon=&quot;aws.cloudfront&quot; aiviz_auto=&quot;20,136,152,40&quot;&gt;&lt;mxCell style=&quot;rounded=1;absoluteArcSize=1;arcSize=16;html=1;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=13;fontColor=#0F172A;fillColor=#EEF2FF;strokeColor=#4F46E5;strokeWidth=1.5;align=left;spacingLeft=44;&quot; vertex=&quot;1&quot; parent=&quot;aws&quot;&gt;&lt;mxGeometry x=&quot;20&quot; y=&quot;136&quot; width=&quot;152&quot; height=&quot;40&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;user__icon&quot; label=&quot;&quot; aiviz_type=&quot;icon&quot;&gt;&lt;mxCell style=&quot;outlineConnect=0;aspect=fixed;html=1;sketch=0;shape=mxgraph.aws4.users;fillColor=#232F3E;strokeColor=none;&quot; vertex=&quot;1&quot; parent=&quot;user&quot;&gt;&lt;mxGeometry x=&quot;10&quot; y=&quot;6&quot; width=&quot;28&quot; height=&quot;28&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;api__icon&quot; label=&quot;&quot; aiviz_type=&quot;icon&quot;&gt;&lt;mxCell style=&quot;outlineConnect=0;aspect=fixed;html=1;sketch=0;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.api_gateway;fillColor=#8C4FFF;strokeColor=#ffffff;&quot; vertex=&quot;1&quot; parent=&quot;api&quot;&gt;&lt;mxGeometry x=&quot;10&quot; y=&quot;6&quot; width=&quot;28&quot; height=&quot;28&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;sign__icon&quot; label=&quot;&quot; aiviz_type=&quot;icon&quot;&gt;&lt;mxCell style=&quot;outlineConnect=0;aspect=fixed;html=1;sketch=0;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.lambda;fillColor=#ED7100;strokeColor=#ffffff;&quot; vertex=&quot;1&quot; parent=&quot;sign&quot;&gt;&lt;mxGeometry x=&quot;10&quot; y=&quot;6&quot; width=&quot;28&quot; height=&quot;28&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;bucket__icon&quot; label=&quot;&quot; aiviz_type=&quot;icon&quot;&gt;&lt;mxCell style=&quot;outlineConnect=0;aspect=fixed;html=1;sketch=0;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.s3;fillColor=#7AA116;strokeColor=#ffffff;&quot; vertex=&quot;1&quot; parent=&quot;bucket&quot;&gt;&lt;mxGeometry x=&quot;10&quot; y=&quot;14&quot; width=&quot;28&quot; height=&quot;28&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;queue__icon&quot; label=&quot;&quot; aiviz_type=&quot;icon&quot;&gt;&lt;mxCell style=&quot;outlineConnect=0;aspect=fixed;html=1;sketch=0;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.sqs;fillColor=#E7157B;strokeColor=#ffffff;&quot; vertex=&quot;1&quot; parent=&quot;queue&quot;&gt;&lt;mxGeometry x=&quot;10&quot; y=&quot;6&quot; width=&quot;28&quot; height=&quot;28&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;resize__icon&quot; label=&quot;&quot; aiviz_type=&quot;icon&quot;&gt;&lt;mxCell style=&quot;outlineConnect=0;aspect=fixed;html=1;sketch=0;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.lambda;fillColor=#ED7100;strokeColor=#ffffff;&quot; vertex=&quot;1&quot; parent=&quot;resize&quot;&gt;&lt;mxGeometry x=&quot;10&quot; y=&quot;6&quot; width=&quot;28&quot; height=&quot;28&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;table__icon&quot; label=&quot;&quot; aiviz_type=&quot;icon&quot;&gt;&lt;mxCell style=&quot;outlineConnect=0;aspect=fixed;html=1;sketch=0;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.dynamodb;fillColor=#C925D1;strokeColor=#ffffff;&quot; vertex=&quot;1&quot; parent=&quot;table&quot;&gt;&lt;mxGeometry x=&quot;10&quot; y=&quot;14&quot; width=&quot;28&quot; height=&quot;28&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;cdn__icon&quot; label=&quot;&quot; aiviz_type=&quot;icon&quot;&gt;&lt;mxCell style=&quot;outlineConnect=0;aspect=fixed;html=1;sketch=0;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.cloudfront;fillColor=#8C4FFF;strokeColor=#ffffff;&quot; vertex=&quot;1&quot; parent=&quot;cdn&quot;&gt;&lt;mxGeometry x=&quot;10&quot; y=&quot;6&quot; width=&quot;28&quot; height=&quot;28&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;e_user__api&quot; label=&quot;POST /uploads&quot; aiviz_edge=&quot;user-&amp;gt;api&quot; aiviz_auto=&quot;302,76 274,76 274,140 284,140&quot;&gt;&lt;mxCell style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;endArrow=blockThin;endFill=1;endSize=7;startArrow=none;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=0.333;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;user&quot; target=&quot;api&quot;&gt;&lt;mxGeometry x=&quot;-0.796&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;Array as=&quot;points&quot;&gt;&lt;mxPoint x=&quot;302&quot; y=&quot;76&quot;/&gt;&lt;mxPoint x=&quot;274&quot; y=&quot;76&quot;/&gt;&lt;mxPoint x=&quot;274&quot; y=&quot;140&quot;/&gt;&lt;mxPoint x=&quot;284&quot; y=&quot;140&quot;/&gt;&lt;/Array&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;e_api__sign&quot; label=&quot;invoke&quot; aiviz_edge=&quot;api-&amp;gt;sign&quot; aiviz_auto=&quot;&quot;&gt;&lt;mxCell style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;endArrow=blockThin;endFill=1;endSize=7;startArrow=none;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;api&quot; target=&quot;sign&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;e_sign__bucket&quot; label=&quot;presigned PUT&quot; aiviz_edge=&quot;sign-&amp;gt;bucket&quot; aiviz_auto=&quot;284,395 150,395&quot;&gt;&lt;mxCell style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;endArrow=blockThin;endFill=1;endSize=7;startArrow=none;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;sign&quot; target=&quot;bucket&quot;&gt;&lt;mxGeometry x=&quot;-0.090&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;Array as=&quot;points&quot;&gt;&lt;mxPoint x=&quot;284&quot; y=&quot;395&quot;/&gt;&lt;mxPoint x=&quot;150&quot; y=&quot;395&quot;/&gt;&lt;/Array&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;e_user__bucket&quot; label=&quot;upload&quot; aiviz_edge=&quot;user-&amp;gt;bucket&quot; aiviz_auto=&quot;352,76 381,76 381,140 370,140 370,405 188,405&quot;&gt;&lt;mxCell style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;endArrow=blockThin;endFill=1;endSize=7;startArrow=none;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=0.667;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;user&quot; target=&quot;bucket&quot;&gt;&lt;mxGeometry x=&quot;-0.710&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;Array as=&quot;points&quot;&gt;&lt;mxPoint x=&quot;352&quot; y=&quot;76&quot;/&gt;&lt;mxPoint x=&quot;381&quot; y=&quot;76&quot;/&gt;&lt;mxPoint x=&quot;381&quot; y=&quot;140&quot;/&gt;&lt;mxPoint x=&quot;370&quot; y=&quot;140&quot;/&gt;&lt;mxPoint x=&quot;370&quot; y=&quot;405&quot;/&gt;&lt;mxPoint x=&quot;188&quot; y=&quot;405&quot;/&gt;&lt;/Array&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;e_bucket__queue&quot; label=&quot;ObjectCreated&quot; aiviz_edge=&quot;bucket-&amp;gt;queue&quot; aiviz_auto=&quot;175,481 222,481&quot;&gt;&lt;mxCell style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;endArrow=blockThin;endFill=1;endSize=7;startArrow=none;dashed=1;dashPattern=6 4;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=0.667;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;bucket&quot; target=&quot;queue&quot;&gt;&lt;mxGeometry x=&quot;0.453&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;Array as=&quot;points&quot;&gt;&lt;mxPoint x=&quot;175&quot; y=&quot;481&quot;/&gt;&lt;mxPoint x=&quot;222&quot; y=&quot;481&quot;/&gt;&lt;/Array&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;e_queue__resize&quot; label=&quot;poll&quot; aiviz_edge=&quot;queue-&amp;gt;resize&quot; aiviz_auto=&quot;222,613 175,613&quot;&gt;&lt;mxCell style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;endArrow=blockThin;endFill=1;endSize=7;startArrow=none;dashed=1;dashPattern=6 4;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.667;entryY=0;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;queue&quot; target=&quot;resize&quot;&gt;&lt;mxGeometry x=&quot;-0.453&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;Array as=&quot;points&quot;&gt;&lt;mxPoint x=&quot;222&quot; y=&quot;613&quot;/&gt;&lt;mxPoint x=&quot;175&quot; y=&quot;613&quot;/&gt;&lt;/Array&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;e_resize__bucket&quot; label=&quot;write variants&quot; aiviz_edge=&quot;resize-&amp;gt;bucket&quot; aiviz_auto=&quot;&quot;&gt;&lt;mxCell style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;endArrow=blockThin;endFill=1;endSize=7;startArrow=none;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=0.333;exitY=0;exitDx=0;exitDy=0;entryX=0.333;entryY=1;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;resize&quot; target=&quot;bucket&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot; x=&quot;-0.350&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;e_resize__table&quot; label=&quot;index&quot; aiviz_edge=&quot;resize-&amp;gt;table&quot; aiviz_auto=&quot;&quot;&gt;&lt;mxCell style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;endArrow=blockThin;endFill=1;endSize=7;startArrow=none;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;resize&quot; target=&quot;table&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;object id=&quot;e_cdn__bucket&quot; label=&quot;origin&quot; aiviz_edge=&quot;cdn-&amp;gt;bucket&quot; aiviz_auto=&quot;&quot;&gt;&lt;mxCell style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;endArrow=blockThin;endFill=1;endSize=7;startArrow=none;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;cdn&quot; target=&quot;bucket&quot;&gt;&lt;mxGeometry x=&quot;-0.152&quot; relative=&quot;1&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;/object&gt;&lt;/root&gt;&lt;/mxGraphModel&gt;&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><rect fill="#FFFFFF" width="100%" height="100%" x="0" y="0" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));"/><g><g data-cell-id="0"><g data-cell-id="1"><g data-cell-id="aws"><g transform="translate(0.5,0.5)"><rect x="16" y="173" width="375" height="622" rx="10" ry="10" fill="#f8fafc" stroke="#cbd5e1" stroke-dasharray="4 4" pointer-events="all" style="fill: light-dark(rgb(248, 250, 252), rgb(21, 23, 25)); stroke: light-dark(rgb(203, 213, 225), rgb(47, 56, 66));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-start; width: 359px; height: 1px; padding-top: 186px; margin-left: 32px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; color: #64748B; "><div style="display: inline-block; font-size: 11px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#64748B, #7e8c9f); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">AWS account</div></div></div></foreignObject><text x="32" y="197" fill="#64748B" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="11px" font-weight="bold" style="fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">AWS account</text></switch></g></g><g data-cell-id="api"><g><rect x="208" y="213" width="152" height="40" rx="8" ry="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5" pointer-events="all" style="fill: light-dark(rgb(238, 242, 255), rgb(26, 29, 40)); stroke: light-dark(rgb(79, 70, 229), rgb(162, 154, 255));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 106px; height: 1px; padding-top: 233px; margin-left: 254px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; color: #0F172A; "><div style="display: inline-block; font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#0F172A, #d3daea); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-weight:600">Upload API</span></div></div></div></foreignObject><text x="254" y="237" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">Upload API</text></switch></g></g><g data-cell-id="api__icon"><g transform="translate(0.5,0.5)"><path d="M 218 219 L 246 219 L 246 247 L 218 247 Z" fill="#8c4fff" stroke="none" pointer-events="all" style="fill: light-dark(rgb(140, 79, 255), rgb(177, 125, 255));"/><path d="M 229.63 239.26 L 230.8 239.26 L 230.8 238.45 L 229.63 238.45 Z M 231.6 239.26 L 232.8 239.26 L 232.8 238.45 L 231.6 238.45 Z M 226.8 222.87 L 221.61 225.45 L 221.61 241.48 L 226.8 243.24 Z M 227.6 227.97 L 227.6 238.45 L 228.8 238.45 L 228.8 239.26 L 227.6 239.26 L 227.6 243.8 C 227.6 243.93 227.54 244.05 227.44 244.12 C 227.37 244.17 227.29 244.2 227.2 244.2 C 227.16 244.2 227.12 244.19 227.08 244.18 L 221.08 242.15 C 220.92 242.1 220.81 241.94 220.81 241.77 L 220.81 225.2 C 220.81 225.05 220.9 224.9 221.03 224.84 L 227.03 221.86 C 227.15 221.8 227.3 221.81 227.42 221.88 C 227.53 221.95 227.6 222.08 227.6 222.22 L 227.6 227.17 L 228.8 227.17 L 228.8 227.97 Z M 233.6 239.26 L 234.8 239.26 L 234.8 238.45 L 233.6 238.45 Z M 233.62 227.97 L 234.8 227.97 L 234.8 227.17 L 233.62 227.17 Z M 231.63 227.97 L 232.8 227.97 L 232.8 227.17 L 231.63 227.17 Z M 229.63 227.97 L 230.8 227.97 L 230.8 227.17 L 229.63 227.17 Z M 242.39 225.45 L 237.2 222.87 L 237.2 243.24 L 242.39 241.48 Z M 243.19 241.77 C 243.19 241.94 243.08 242.1 242.92 242.15 L 236.92 244.18 C 236.88 244.19 236.84 244.2 236.8 244.2 C 236.71 244.2 236.63 244.17 236.56 244.12 C 236.46 244.05 236.4 243.93 236.4 243.8 L 236.4 239.26 L 235.62 239.26 L 235.62 238.45 L 236.4 238.45 L 236.4 227.97 L 235.62 227.97 L 235.62 227.17 L 236.4 227.17 L 236.4 222.22 C 236.4 222.08 236.47 221.95 236.58 221.88 C 236.7 221.81 236.85 221.8 236.97 221.86 L 242.97 224.84 C 243.1 224.9 243.19 225.05 243.19 225.2 Z M 233.17 230.54 L 232.43 230.25 L 230.43 235.49 L 231.17 235.77 Z M 235.88 233.09 C 236.04 232.94 236.04 232.68 235.88 232.52 L 234.28 230.91 L 233.72 231.48 L 235.03 232.81 L 233.72 234.14 L 234.28 234.71 Z M 229.72 234.71 L 228.12 233.09 C 227.96 232.94 227.96 232.68 228.12 232.52 L 229.72 230.91 L 230.28 231.48 L 228.97 232.81 L 230.28 234.14 Z" fill="#ffffff" stroke="none" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));"/></g></g></g><g data-cell-id="sign"><g><rect x="208" y="309" width="152" height="40" rx="8" ry="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5" stroke-dasharray="9 6" pointer-events="all" style="fill: light-dark(rgb(238, 242, 255), rgb(26, 29, 40)); stroke: light-dark(rgb(79, 70, 229), rgb(162, 154, 255));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 106px; height: 1px; padding-top: 329px; margin-left: 254px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; color: #0F172A; "><div style="display: inline-block; font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#0F172A, #d3daea); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-weight:600">Presign</span></div></div></div></foreignObject><text x="254" y="333" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">Presign</text></switch></g></g><g data-cell-id="sign__icon"><g transform="translate(0.5,0.5)"><path d="M 218 315 L 246 315 L 246 343 L 218 343 Z" fill="#ed7100" stroke="none" pointer-events="all" style="fill: light-dark(rgb(237, 113, 0), rgb(216, 109, 12));"/><path d="M 227.21 339.4 L 222.25 339.4 L 227.74 327.92 L 230.23 333.04 Z M 228.1 326.82 C 228.03 326.68 227.89 326.6 227.74 326.6 L 227.74 326.6 C 227.58 326.6 227.44 326.68 227.38 326.82 L 221.25 339.63 C 221.19 339.75 221.2 339.9 221.27 340.01 C 221.35 340.13 221.47 340.2 221.61 340.2 L 227.47 340.2 C 227.62 340.2 227.76 340.11 227.83 339.97 L 231.04 333.21 C 231.09 333.1 231.09 332.97 231.03 332.87 Z M 242.01 339.4 L 237.07 339.4 L 229.16 322.83 C 229.09 322.69 228.95 322.6 228.79 322.6 L 225.57 322.6 L 225.57 318.6 L 231.9 318.6 L 239.78 335.17 C 239.84 335.31 239.99 335.4 240.14 335.4 L 242.01 335.4 Z M 242.41 334.6 L 240.39 334.6 L 232.51 318.03 C 232.45 317.89 232.31 317.8 232.15 317.8 L 225.17 317.8 C 224.95 317.8 224.77 317.98 224.77 318.2 L 224.76 323 C 224.76 323.11 224.81 323.21 224.88 323.28 C 224.96 323.36 225.06 323.4 225.16 323.4 L 228.54 323.4 L 236.46 339.97 C 236.53 340.11 236.67 340.2 236.82 340.2 L 242.41 340.2 C 242.63 340.2 242.81 340.02 242.81 339.8 L 242.81 335 C 242.81 334.78 242.63 334.6 242.41 334.6 Z" fill="#ffffff" stroke="none" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));"/></g></g></g><g data-cell-id="bucket"><g><path d="M 74 423 C 74 418.58 108.03 415 150 415 C 170.16 415 189.49 415.84 203.74 417.34 C 217.99 418.84 226 420.88 226 423 L 226 463 C 226 467.42 191.97 471 150 471 C 108.03 471 74 467.42 74 463 Z" fill="#ecfdf5" stroke="#059669" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(236, 253, 245), rgb(13, 27, 21)); stroke: light-dark(rgb(5, 150, 105), rgb(42, 167, 128));"/><path d="M 226 423 C 226 427.42 191.97 431 150 431 C 108.03 431 74 427.42 74 423" fill="none" stroke="#059669" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="stroke: light-dark(rgb(5, 150, 105), rgb(42, 167, 128));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 106px; height: 1px; padding-top: 450px; margin-left: 120px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; color: #0F172A; "><div style="display: inline-block; font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#0F172A, #d3daea); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-weight:600">Raw images</span></div></div></div></foreignObject><text x="120" y="454" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">Raw images</text></switch></g></g><g data-cell-id="bucket__icon"><g transform="translate(0.5,0.5)"><path d="M 84 429 L 112 429 L 112 457 L 84 457 Z" fill="#7aa116" stroke="none" pointer-events="all" style="fill: light-dark(rgb(122, 161, 22), rgb(97, 130, 11));"/><path d="M 106.36 444.16 L 106.51 443.08 C 107.93 443.92 107.95 444.27 107.95 444.28 C 107.94 444.29 107.7 444.49 106.36 444.16 Z M 105.58 443.94 C 103.13 443.2 99.72 441.64 98.34 440.98 C 98.34 440.98 98.35 440.97 98.35 440.97 C 98.35 440.44 97.91 440.01 97.38 440.01 C 96.85 440.01 96.42 440.44 96.42 440.97 C 96.42 441.5 96.85 441.93 97.38 441.93 C 97.62 441.93 97.83 441.84 97.99 441.7 C 99.62 442.47 103 444.01 105.47 444.74 L 104.49 451.62 C 104.49 451.64 104.49 451.66 104.49 451.68 C 104.49 452.29 101.8 453.4 97.42 453.4 C 92.99 453.4 90.28 452.29 90.28 451.68 C 90.28 451.66 90.28 451.64 90.28 451.63 L 88.24 436.74 C 90 437.96 93.8 438.6 97.42 438.6 C 101.05 438.6 104.83 437.96 106.6 436.75 Z M 88.02 435.19 C 88.05 434.66 91.08 432.6 97.42 432.6 C 103.77 432.6 106.79 434.66 106.82 435.19 L 106.82 435.37 C 106.48 436.55 102.56 437.8 97.42 437.8 C 92.28 437.8 88.36 436.55 88.02 435.37 Z M 107.62 435.2 C 107.62 433.81 103.65 431.8 97.42 431.8 C 91.2 431.8 87.22 433.81 87.22 435.2 L 87.26 435.5 L 89.48 451.71 C 89.53 453.52 94.37 454.2 97.42 454.2 C 101.21 454.2 105.23 453.33 105.29 451.71 L 106.25 444.95 C 106.78 445.08 107.22 445.15 107.57 445.15 C 108.04 445.15 108.36 445.03 108.56 444.8 C 108.72 444.61 108.78 444.38 108.73 444.14 C 108.63 443.58 107.97 442.99 106.63 442.22 L 107.58 435.52 Z" fill="#ffffff" stroke="none" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));"/></g></g></g><g data-cell-id="queue"><g><rect x="146" y="527" width="152" height="40" rx="20" ry="20" fill="#fff7ed" stroke="#d97706" stroke-width="1.5" pointer-events="all" style="fill: light-dark(rgb(255, 247, 237), rgb(30, 23, 15)); stroke: light-dark(rgb(217, 119, 6), rgb(197, 113, 16));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 106px; height: 1px; padding-top: 547px; margin-left: 192px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; color: #0F172A; "><div style="display: inline-block; font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#0F172A, #d3daea); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-weight:600">resize-jobs</span></div></div></div></foreignObject><text x="192" y="551" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">resize-jobs</text></switch></g></g><g data-cell-id="queue__icon"><g transform="translate(0.5,0.5)"><path d="M 156 533 L 184 533 L 184 561 L 156 561 Z" fill="#e7157b" stroke="none" pointer-events="all" style="fill: light-dark(rgb(231, 21, 123), rgb(255, 129, 217));"/><path d="M 165.57 548.45 L 166.75 547.28 C 166.82 547.21 166.86 547.11 166.87 547.01 C 166.87 546.9 166.82 546.8 166.75 546.73 L 165.57 545.55 L 165.02 546.1 L 165.52 546.61 L 163.72 546.61 L 163.72 547.39 L 165.53 547.39 L 165.02 547.89 Z M 174.56 548.48 L 176.13 547.31 C 176.23 547.24 176.29 547.12 176.29 547 C 176.29 546.88 176.23 546.76 176.13 546.69 L 174.56 545.52 L 174.09 546.14 L 174.72 546.61 L 173.15 546.61 L 173.15 547.39 L 174.72 547.39 L 174.09 547.86 Z M 168.12 547 C 168.12 547.83 167.98 548.61 167.71 549.29 C 168.41 549.02 169.21 548.88 170.01 548.88 C 170.8 548.88 171.6 549.02 172.31 549.29 C 172.04 548.61 171.9 547.83 171.9 547 C 171.9 546.17 172.04 545.39 172.31 544.71 C 170.89 545.25 169.12 545.25 167.71 544.71 C 167.98 545.39 168.12 546.17 168.12 547 Z M 166.19 550.79 C 166.12 550.71 166.08 550.61 166.08 550.51 C 166.08 550.41 166.12 550.31 166.19 550.24 C 166.91 549.53 167.33 548.32 167.33 547 C 167.33 545.68 166.91 544.47 166.19 543.76 C 166.12 543.69 166.08 543.59 166.08 543.49 C 166.08 543.39 166.12 543.29 166.19 543.21 C 166.35 543.06 166.6 543.06 166.75 543.21 C 168.27 544.72 171.74 544.72 173.26 543.21 C 173.42 543.06 173.67 543.06 173.82 543.21 C 173.9 543.29 173.93 543.39 173.93 543.49 C 173.93 543.59 173.9 543.69 173.82 543.76 C 173.11 544.47 172.68 545.68 172.68 547 C 172.68 548.32 173.11 549.53 173.82 550.24 C 173.9 550.31 173.93 550.41 173.93 550.51 C 173.93 550.61 173.9 550.71 173.82 550.79 C 173.74 550.86 173.64 550.9 173.54 550.9 C 173.44 550.9 173.34 550.86 173.26 550.79 C 171.74 549.28 168.27 549.28 166.75 550.79 C 166.6 550.94 166.35 550.94 166.19 550.79 Z M 180.21 547 C 180.21 546.64 180.06 546.3 179.8 546.04 C 179.54 545.77 179.19 545.64 178.83 545.64 C 178.48 545.64 178.13 545.77 177.87 546.04 C 177.33 546.57 177.33 547.43 177.87 547.96 C 178.4 548.5 179.27 548.5 179.8 547.96 C 180.06 547.71 180.21 547.37 180.21 547 Z M 180.36 548.52 C 179.94 548.93 179.39 549.14 178.83 549.14 C 178.28 549.14 177.73 548.93 177.31 548.52 C 176.47 547.68 176.47 546.32 177.31 545.49 C 178.15 544.65 179.52 544.65 180.36 545.49 C 181.2 546.32 181.2 547.68 180.36 548.52 Z M 162.53 547.01 C 162.53 546.65 162.39 546.31 162.13 546.05 C 161.87 545.79 161.53 545.65 161.16 545.65 C 160.8 545.65 160.45 545.79 160.2 546.05 C 159.94 546.31 159.79 546.65 159.79 547.01 C 159.79 547.37 159.94 547.72 160.2 547.97 C 160.71 548.49 161.62 548.49 162.13 547.97 C 162.39 547.72 162.53 547.37 162.53 547.01 Z M 162.69 548.53 C 162.27 548.94 161.72 549.15 161.16 549.15 C 160.61 549.15 160.06 548.94 159.64 548.53 C 158.8 547.69 158.8 546.33 159.64 545.5 C 160.48 544.66 161.85 544.66 162.69 545.5 C 163.53 546.33 163.53 547.69 162.69 548.53 Z M 175.85 552.83 C 174.28 554.39 172.19 555.25 169.98 555.25 C 167.76 555.25 165.67 554.39 164.11 552.83 C 163.03 551.76 162.44 550.49 162.13 549.6 L 161.39 549.86 C 161.72 550.82 162.37 552.21 163.55 553.38 C 165.27 555.09 167.55 556.03 169.98 556.03 C 172.4 556.03 174.69 555.09 176.4 553.38 C 177.39 552.4 178.18 551.15 178.63 549.86 L 177.88 549.61 C 177.48 550.78 176.75 551.93 175.85 552.83 Z M 162.13 544.4 L 161.39 544.14 C 161.86 542.78 162.63 541.53 163.55 540.62 C 165.27 538.91 167.55 537.97 169.98 537.97 C 172.4 537.97 174.68 538.91 176.4 540.62 C 177.37 541.58 178.18 542.86 178.63 544.14 L 177.88 544.4 C 177.47 543.23 176.73 542.05 175.84 541.17 C 174.28 539.61 172.19 538.75 169.98 538.75 C 167.76 538.75 165.67 539.61 164.11 541.17 C 163.27 542 162.57 543.15 162.13 544.4 Z" fill="#ffffff" stroke="none" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));"/></g></g></g><g data-cell-id="resize"><g><rect x="74" y="623" width="152" height="40" rx="8" ry="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5" stroke-dasharray="9 6" pointer-events="all" style="fill: light-dark(rgb(238, 242, 255), rgb(26, 29, 40)); stroke: light-dark(rgb(79, 70, 229), rgb(162, 154, 255));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 106px; height: 1px; padding-top: 643px; margin-left: 120px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; color: #0F172A; "><div style="display: inline-block; font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#0F172A, #d3daea); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-weight:600">Resizer</span></div></div></div></foreignObject><text x="120" y="647" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">Resizer</text></switch></g></g><g data-cell-id="resize__icon"><g transform="translate(0.5,0.5)"><path d="M 84 629 L 112 629 L 112 657 L 84 657 Z" fill="#ed7100" stroke="none" pointer-events="all" style="fill: light-dark(rgb(237, 113, 0), rgb(216, 109, 12));"/><path d="M 93.21 653.4 L 88.25 653.4 L 93.74 641.92 L 96.23 647.04 Z M 94.1 640.82 C 94.03 640.68 93.89 640.6 93.74 640.6 L 93.74 640.6 C 93.58 640.6 93.44 640.68 93.38 640.82 L 87.25 653.63 C 87.19 653.75 87.2 653.9 87.27 654.01 C 87.35 654.13 87.47 654.2 87.61 654.2 L 93.47 654.2 C 93.62 654.2 93.76 654.11 93.83 653.97 L 97.04 647.21 C 97.09 647.1 97.09 646.97 97.03 646.87 Z M 108.01 653.4 L 103.07 653.4 L 95.16 636.83 C 95.09 636.69 94.95 636.6 94.79 636.6 L 91.57 636.6 L 91.57 632.6 L 97.9 632.6 L 105.78 649.17 C 105.84 649.31 105.99 649.4 106.14 649.4 L 108.01 649.4 Z M 108.41 648.6 L 106.39 648.6 L 98.51 632.03 C 98.45 631.89 98.31 631.8 98.15 631.8 L 91.17 631.8 C 90.95 631.8 90.77 631.98 90.77 632.2 L 90.76 637 C 90.76 637.11 90.81 637.21 90.88 637.28 C 90.96 637.36 91.06 637.4 91.16 637.4 L 94.54 637.4 L 102.46 653.97 C 102.53 654.11 102.67 654.2 102.82 654.2 L 108.41 654.2 C 108.63 654.2 108.81 654.02 108.81 653.8 L 108.81 649 C 108.81 648.78 108.63 648.6 108.41 648.6 Z" fill="#ffffff" stroke="none" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));"/></g></g></g><g data-cell-id="table"><g><path d="M 74 727 C 74 722.58 108.03 719 150 719 C 170.16 719 189.49 719.84 203.74 721.34 C 217.99 722.84 226 724.88 226 727 L 226 767 C 226 771.42 191.97 775 150 775 C 108.03 775 74 771.42 74 767 Z" fill="#ecfdf5" stroke="#059669" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(236, 253, 245), rgb(13, 27, 21)); stroke: light-dark(rgb(5, 150, 105), rgb(42, 167, 128));"/><path d="M 226 727 C 226 731.42 191.97 735 150 735 C 108.03 735 74 731.42 74 727" fill="none" stroke="#059669" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="stroke: light-dark(rgb(5, 150, 105), rgb(42, 167, 128));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 106px; height: 1px; padding-top: 754px; margin-left: 120px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; color: #0F172A; "><div style="display: inline-block; font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#0F172A, #d3daea); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-weight:600">Image index</span></div></div></div></foreignObject><text x="120" y="758" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">Image index</text></switch></g></g><g data-cell-id="table__icon"><g transform="translate(0.5,0.5)"><path d="M 84 733 L 112 733 L 112 761 L 84 761 Z" fill="#c925d1" stroke="none" pointer-events="all" style="fill: light-dark(rgb(201, 37, 209), rgb(255, 124, 255));"/><path d="M 102.82 752.94 C 101.48 754.02 98.68 754.59 96 754.59 C 93.32 754.59 90.52 754.02 89.18 752.94 L 89.18 755.11 L 89.19 755.11 C 89.19 756.2 91.98 757.41 96 757.41 C 100.02 757.41 102.81 756.2 102.82 755.12 Z M 102.82 748.81 L 103.62 748.8 L 103.62 748.81 C 103.62 749.29 103.38 749.74 102.91 750.16 C 103.48 750.66 103.62 751.15 103.62 751.5 C 103.62 751.51 103.62 751.51 103.62 751.51 L 103.62 755.11 L 103.62 755.11 C 103.62 757.12 99.69 758.2 96 758.2 C 92.32 758.2 88.4 757.12 88.39 755.13 C 88.39 755.13 88.38 755.12 88.38 755.12 L 88.38 751.5 C 88.38 751.5 88.39 751.5 88.39 751.5 C 88.39 751.15 88.53 750.66 89.1 750.16 C 88.53 749.65 88.39 749.17 88.39 748.82 L 88.39 748.82 C 88.39 748.82 88.38 748.81 88.38 748.81 L 88.38 745.19 C 88.38 745.19 88.39 745.19 88.39 745.19 C 88.39 744.84 88.53 744.35 89.1 743.85 C 88.53 743.35 88.39 742.86 88.39 742.51 L 88.39 742.51 C 88.39 742.51 88.38 742.51 88.38 742.5 L 88.38 738.89 C 88.38 738.88 88.39 738.88 88.39 738.88 C 88.39 736.88 92.31 735.8 96 735.8 C 98.09 735.8 100.09 736.13 101.5 736.71 L 101.19 737.44 C 99.88 736.9 97.99 736.59 96 736.59 C 91.98 736.59 89.19 737.8 89.19 738.89 C 89.19 739.97 91.98 741.18 96 741.18 C 96.11 741.18 96.22 741.18 96.32 741.18 L 96.36 741.97 C 96.24 741.97 96.12 741.97 96 741.97 C 93.32 741.97 90.52 741.4 89.18 740.32 L 89.18 742.5 L 89.19 742.5 L 89.19 742.51 C 89.19 742.92 89.62 743.28 89.97 743.52 C 91.05 744.2 92.98 744.67 95.13 744.77 L 95.09 745.56 C 92.91 745.46 91.01 745.01 89.78 744.32 C 89.48 744.54 89.19 744.85 89.19 745.2 C 89.19 746.28 91.98 747.49 96 747.49 C 96.4 747.49 96.79 747.48 97.17 747.45 L 97.22 748.24 C 96.83 748.27 96.41 748.28 96 748.28 C 93.32 748.28 90.52 747.71 89.18 746.63 L 89.18 748.8 L 89.19 748.8 C 89.19 749.23 89.62 749.59 89.97 749.82 C 91.2 750.61 93.51 751.1 96 751.1 L 96.18 751.1 L 96.18 751.89 L 96 751.89 C 93.47 751.89 91.18 751.42 89.77 750.63 C 89.47 750.85 89.19 751.16 89.19 751.5 C 89.19 752.59 91.98 753.8 96 753.8 C 100.02 753.8 102.81 752.59 102.82 751.51 L 102.82 751.5 L 102.82 751.5 C 102.82 751.16 102.53 750.85 102.23 750.63 C 102.03 750.74 101.82 750.84 101.59 750.94 L 101.28 750.21 C 101.57 750.09 101.82 749.96 102.03 749.82 C 102.39 749.59 102.82 749.22 102.82 748.81 Z M 106.25 743.01 L 104 743.01 C 103.87 743.01 103.75 742.94 103.67 742.83 C 103.6 742.72 103.58 742.59 103.63 742.46 L 105 739.06 L 99.83 739.06 L 97.43 743.82 L 99.98 743.82 C 100.11 743.82 100.23 743.88 100.31 743.98 C 100.38 744.08 100.41 744.21 100.37 744.33 L 98.09 751.44 Z M 107.47 742.88 L 97.47 753.22 C 97.4 753.3 97.29 753.34 97.19 753.34 C 97.11 753.34 97.04 753.32 96.98 753.28 C 96.82 753.19 96.75 753 96.8 752.82 L 99.44 744.61 L 96.78 744.61 C 96.65 744.61 96.52 744.54 96.44 744.42 C 96.37 744.3 96.37 744.16 96.43 744.04 L 99.23 738.48 C 99.3 738.35 99.43 738.26 99.59 738.26 L 105.59 738.26 C 105.72 738.26 105.84 738.33 105.92 738.44 C 105.99 738.54 106.01 738.68 105.96 738.8 L 104.59 742.21 L 107.18 742.21 C 107.34 742.21 107.49 742.31 107.55 742.45 C 107.62 742.6 107.58 742.77 107.47 742.88 Z M 89.77 755.27 C 90.33 755.59 91.05 755.86 91.89 756.07 L 92.08 755.3 C 91.32 755.11 90.66 754.86 90.16 754.58 Z M 91.89 749.72 L 92.08 748.95 C 91.32 748.76 90.66 748.51 90.16 748.23 L 89.77 748.92 C 90.33 749.24 91.05 749.51 91.89 749.72 Z M 89.77 742.57 L 90.16 741.88 C 90.66 742.16 91.32 742.41 92.08 742.6 L 91.89 743.37 C 91.05 743.16 90.33 742.89 89.77 742.57 Z" fill="#ffffff" stroke="none" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));"/></g></g></g><g data-cell-id="cdn"><g><rect x="36" y="309" width="152" height="40" rx="8" ry="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5" pointer-events="all" style="fill: light-dark(rgb(238, 242, 255), rgb(26, 29, 40)); stroke: light-dark(rgb(79, 70, 229), rgb(162, 154, 255));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 106px; height: 1px; padding-top: 329px; margin-left: 82px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; color: #0F172A; "><div style="display: inline-block; font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#0F172A, #d3daea); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-weight:600">CDN</span></div></div></div></foreignObject><text x="82" y="333" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">CDN</text></switch></g></g><g data-cell-id="cdn__icon"><g transform="translate(0.5,0.5)"><path d="M 46 315 L 74 315 L 74 343 L 46 343 Z" fill="#8c4fff" stroke="none" pointer-events="all" style="fill: light-dark(rgb(140, 79, 255), rgb(177, 125, 255));"/><path d="M 66.05 333.85 C 66.05 333.19 65.51 332.65 64.85 332.65 C 64.19 332.65 63.65 333.19 63.65 333.85 C 63.65 334.51 64.19 335.05 64.85 335.05 C 65.51 335.05 66.05 334.51 66.05 333.85 Z M 66.85 333.85 C 66.85 334.95 65.95 335.85 64.85 335.85 C 63.75 335.85 62.85 334.95 62.85 333.85 C 62.85 332.75 63.75 331.85 64.85 331.85 C 65.95 331.85 66.85 332.75 66.85 333.85 Z M 56.16 328.08 C 56.16 327.42 55.62 326.88 54.96 326.88 C 54.29 326.88 53.76 327.42 53.76 328.08 C 53.76 328.74 54.29 329.28 54.96 329.28 C 55.62 329.28 56.16 328.74 56.16 328.08 Z M 56.96 328.08 C 56.96 329.18 56.06 330.08 54.96 330.08 C 53.85 330.08 52.96 329.18 52.96 328.08 C 52.96 326.97 53.85 326.08 54.96 326.08 C 56.06 326.08 56.96 326.97 56.96 328.08 Z M 59.89 321.8 C 59.89 322.46 60.43 323 61.09 323 C 61.75 323 62.29 322.46 62.29 321.8 C 62.29 321.14 61.75 320.6 61.09 320.6 C 60.43 320.6 59.89 321.14 59.89 321.8 Z M 59.09 321.8 C 59.09 320.7 59.99 319.8 61.09 319.8 C 62.19 319.8 63.09 320.7 63.09 321.8 C 63.09 322.91 62.19 323.8 61.09 323.8 C 59.99 323.8 59.09 322.91 59.09 321.8 Z M 70.4 329 C 70.4 325.29 68.41 321.86 65.2 320 C 64.63 320.12 64.07 320.28 63.38 320.53 L 63.11 319.78 C 63.47 319.65 63.79 319.54 64.11 319.45 C 62.82 318.89 61.42 318.6 60 318.6 C 59.32 318.6 58.66 318.67 58.01 318.8 C 58.48 319.07 58.9 319.35 59.3 319.65 L 58.82 320.29 C 58.25 319.86 57.66 319.49 56.88 319.08 C 52.95 320.32 50.12 323.78 49.67 327.85 C 50.5 327.68 51.29 327.59 52.17 327.57 L 52.19 328.37 C 51.27 328.39 50.47 328.49 49.61 328.68 C 49.61 328.79 49.6 328.9 49.6 329 C 49.6 332.46 51.31 335.65 54.13 337.58 C 53.63 336.09 53.38 334.68 53.38 333.3 C 53.38 332.51 53.52 331.87 53.66 331.18 C 53.69 331.03 53.72 330.87 53.76 330.7 L 54.54 330.85 C 54.51 331.02 54.47 331.19 54.44 331.35 C 54.3 332.02 54.18 332.6 54.18 333.3 C 54.18 334.86 54.52 336.48 55.22 338.23 C 56.71 339.01 58.32 339.4 60 339.4 C 61.1 339.4 62.18 339.22 63.2 338.89 C 63.61 338.09 63.91 337.34 64.16 336.48 L 64.92 336.7 C 64.74 337.33 64.53 337.9 64.28 338.47 C 64.93 338.18 65.54 337.82 66.11 337.4 C 65.98 337.06 65.83 336.73 65.66 336.4 L 66.38 336.04 C 66.52 336.32 66.65 336.6 66.77 336.89 C 69.08 334.91 70.4 332.06 70.4 329 Z M 71.2 329 C 71.2 332.49 69.61 335.72 66.85 337.86 C 66.16 338.39 65.42 338.83 64.64 339.19 C 64.3 339.34 63.96 339.48 63.61 339.6 C 62.46 340 61.25 340.2 60 340.2 C 58.16 340.2 56.33 339.74 54.72 338.87 C 51.07 336.92 48.8 333.14 48.8 329 C 48.8 328.73 48.81 328.52 48.82 328.32 C 49.1 323.65 52.3 319.6 56.8 318.27 C 57.82 317.96 58.9 317.8 60 317.8 C 61.92 317.8 63.82 318.3 65.47 319.23 C 69.01 321.21 71.2 324.95 71.2 329 Z M 58.93 323.19 L 58.4 322.58 C 57.5 323.36 56.81 324.2 55.99 325.45 L 56.66 325.89 C 57.43 324.7 58.09 323.92 58.93 323.19 Z M 57.71 328.37 L 57.45 329.13 C 59.29 329.76 60.89 330.76 62.49 332.29 L 63.05 331.72 C 61.36 330.1 59.66 329.04 57.71 328.37 Z M 63.06 323.67 C 64.56 325.96 65.4 328.47 65.57 331.14 L 64.77 331.18 C 64.61 328.66 63.81 326.28 62.39 324.11 Z" fill="#ffffff" stroke="none" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));"/></g></g></g></g><g data-cell-id="user"><g><rect x="251" y="16" width="152" height="40" rx="8" ry="8" fill="#fdf4ff" stroke="#c026d3" stroke-width="1.5" pointer-events="all" style="fill: light-dark(rgb(253, 244, 255), rgb(30, 23, 32)); stroke: light-dark(rgb(192, 38, 211), rgb(255, 127, 255));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 106px; height: 1px; padding-top: 36px; margin-left: 297px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; color: #0F172A; "><div style="display: inline-block; font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#0F172A, #d3daea); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-weight:600">Uploader</span></div></div></div></foreignObject><text x="297" y="40" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">Uploader</text></switch></g></g><g data-cell-id="user__icon"><g><path d="M 277.95 26.64 C 277.95 24.78 279.49 23.27 281.38 23.27 C 283.26 23.27 284.8 24.78 284.8 26.64 C 284.8 28.49 283.26 30 281.38 30 C 279.49 30 277.95 28.49 277.95 26.64 Z M 285.29 31.12 C 284.87 30.87 284.44 30.65 283.99 30.48 C 285.24 29.65 286.07 28.24 286.07 26.64 C 286.07 24.08 283.96 22 281.38 22 C 278.79 22 276.68 24.08 276.68 26.64 C 276.68 28.23 277.5 29.65 278.75 30.48 C 277.94 30.79 277.17 31.24 276.49 31.82 L 277.32 32.78 C 278.46 31.81 279.89 31.27 281.36 31.27 C 282.51 31.27 283.63 31.59 284.61 32.2 C 286.36 33.29 287.5 35.19 287.7 37.27 L 281.36 37.27 L 281.36 38.55 L 288.36 38.55 C 288.72 38.55 289 38.26 289 37.91 C 289 35.15 287.58 32.54 285.29 31.12 Z M 265.22 26.64 C 265.22 24.78 266.76 23.27 268.65 23.27 C 270.54 23.27 272.07 24.78 272.07 26.64 C 272.07 28.49 270.54 30 268.65 30 C 266.76 30 265.22 28.49 265.22 26.64 Z M 268.64 37.27 L 262.3 37.27 C 262.61 33.91 265.33 31.27 268.64 31.27 C 269.78 31.27 270.91 31.59 271.89 32.2 C 272.16 32.37 272.43 32.57 272.68 32.78 L 273.51 31.82 C 273.21 31.56 272.89 31.33 272.56 31.12 C 272.15 30.87 271.71 30.65 271.26 30.48 C 272.52 29.65 273.34 28.24 273.34 26.64 C 273.34 24.08 271.24 22 268.65 22 C 266.06 22 263.95 24.08 263.95 26.64 C 263.95 28.24 264.78 29.65 266.03 30.48 C 263.1 31.59 261 34.5 261 37.91 C 261 38.26 261.29 38.55 261.64 38.55 L 268.64 38.55 Z M 268.67 48.73 C 268.97 45.37 271.7 42.73 275 42.73 C 276.15 42.73 277.27 43.05 278.25 43.66 C 279.99 44.74 281.14 46.64 281.33 48.73 Z M 271.59 38.09 C 271.59 36.24 273.12 34.73 275.01 34.73 C 276.9 34.73 278.43 36.24 278.43 38.09 C 278.43 39.95 276.9 41.45 275.01 41.45 C 273.12 41.45 271.59 39.95 271.59 38.09 Z M 278.92 42.58 C 278.51 42.32 278.08 42.11 277.63 41.94 C 278.88 41.11 279.71 39.69 279.71 38.09 C 279.71 35.53 277.6 33.45 275.01 33.45 C 272.42 33.45 270.32 35.53 270.32 38.09 C 270.32 39.69 271.14 41.11 272.4 41.94 C 269.46 43.05 267.36 45.95 267.36 49.36 C 267.36 49.72 267.65 50 268 50 L 282 50 C 282.35 50 282.64 49.72 282.64 49.36 C 282.64 46.6 281.21 44 278.92 42.58 Z" fill="#232f3e" stroke="none" pointer-events="all" style="fill: light-dark(rgb(35, 47, 62), rgb(189, 199, 212));"/></g></g></g><g data-cell-id="e_user__api"><g><path d="M 301.62 56 L 301.6 70 Q 301.6 76 295.6 76 L 280 76 Q 274 76 274 82 L 274 134 Q 274 140 279 140 L 281.5 140 Q 284 140 284 146 L 284 202.82" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 284 211.32 L 281.17 202.82 L 286.83 202.82 Z" fill="#64748b" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159)); stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 76px; margin-left: 302px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #475569; background-color: #FFFFFF; "><div style="display: inline-block; font-size: 11px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#475569, #9ba7b8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; ">POST /uploads</div></div></div></foreignObject><text x="302" y="79" fill="#475569" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="11px" text-anchor="middle" style="fill: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));">POST /uploads</text></switch></g></g></g><g data-cell-id="e_api__sign"><g><path d="M 284 253 L 284 298.82" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 284 307.32 L 281.17 298.82 L 286.83 298.82 Z" fill="#64748b" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159)); stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 281px; margin-left: 284px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #475569; background-color: #FFFFFF; "><div style="display: inline-block; font-size: 11px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#475569, #9ba7b8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; ">invoke</div></div></div></foreignObject><text x="284" y="284" fill="#475569" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="11px" text-anchor="middle" style="fill: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));">invoke</text></switch></g></g></g><g data-cell-id="e_sign__bucket"><g><path d="M 284 349 L 284 389 Q 284 395 278 395 L 156 395 Q 150 395 150 399.91 L 150 404.82" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 150 413.32 L 147.17 404.82 L 152.83 404.82 Z" fill="#64748b" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159)); stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 395px; margin-left: 239px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #475569; background-color: #FFFFFF; "><div style="display: inline-block; font-size: 11px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#475569, #9ba7b8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; ">presigned PUT</div></div></div></foreignObject><text x="239" y="398" fill="#475569" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="11px" text-anchor="middle" style="fill: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));">presigned PUT</text></switch></g></g></g><g data-cell-id="e_user__bucket"><g><path d="M 352.38 56 L 352.4 70 Q 352.4 76 358.4 76 L 375 76 Q 381 76 381 82 L 381 134 Q 381 140 375.5 140 L 372.75 140 Q 370 140 370 146 L 370 399 Q 370 405 364 405 L 194 405 Q 188 405 188 404.91 L 188 404.82" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 188 413.32 L 185.17 404.82 L 190.83 404.82 Z" fill="#64748b" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159)); stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 111px; margin-left: 381px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #475569; background-color: #FFFFFF; "><div style="display: inline-block; font-size: 11px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#475569, #9ba7b8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; ">upload</div></div></div></foreignObject><text x="381" y="115" fill="#475569" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="11px" text-anchor="middle" style="fill: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));">upload</text></switch></g></g></g><g data-cell-id="e_bucket__queue"><g><path d="M 175.38 471 L 175.39 476 Q 175.4 481 181.4 481 L 216 481 Q 222 481 222 487 L 222 516.82" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" stroke-dasharray="9 6" pointer-events="stroke" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 222 525.32 L 219.17 516.82 L 224.83 516.82 Z" fill="#64748b" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159)); stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 499px; margin-left: 222px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #475569; background-color: #FFFFFF; "><div style="display: inline-block; font-size: 11px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#475569, #9ba7b8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; ">ObjectCreated</div></div></div></foreignObject><text x="222" y="503" fill="#475569" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="11px" text-anchor="middle" style="fill: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));">ObjectCreated</text></switch></g></g></g><g data-cell-id="e_queue__resize"><g><path d="M 222 567 L 222 607 Q 222 613 216 613 L 181.4 613 Q 175.4 613 175.4 612.91 L 175.4 612.82" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" stroke-dasharray="9 6" pointer-events="stroke" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 175.39 621.32 L 172.57 612.82 L 178.23 612.83 Z" fill="#64748b" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159)); stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 595px; margin-left: 222px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #475569; background-color: #FFFFFF; "><div style="display: inline-block; font-size: 11px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#475569, #9ba7b8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; ">poll</div></div></div></foreignObject><text x="222" y="598" fill="#475569" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="11px" text-anchor="middle" style="fill: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));">poll</text></switch></g></g></g><g data-cell-id="e_resize__bucket"><g><path d="M 124.62 623 L 124.62 481.18" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 124.62 472.68 L 127.45 481.18 L 121.78 481.18 Z" fill="#64748b" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159)); stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 574px; margin-left: 125px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #475569; background-color: #FFFFFF; "><div style="display: inline-block; font-size: 11px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#475569, #9ba7b8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; ">write variants</div></div></div></foreignObject><text x="125" y="577" fill="#475569" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="11px" text-anchor="middle" style="fill: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));">write variants</text></switch></g></g></g><g data-cell-id="e_resize__table"><g><path d="M 150 663 L 150 708.82" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 150 717.32 L 147.17 708.82 L 152.83 708.82 Z" fill="#64748b" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159)); stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 691px; margin-left: 150px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #475569; background-color: #FFFFFF; "><div style="display: inline-block; font-size: 11px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#475569, #9ba7b8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; ">index</div></div></div></foreignObject><text x="150" y="694" fill="#475569" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="11px" text-anchor="middle" style="fill: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));">index</text></switch></g></g></g><g data-cell-id="e_cdn__bucket"><g><path d="M 112 349 L 112 404.82" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 112 413.32 L 109.17 404.82 L 114.83 404.82 Z" fill="#64748b" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159)); stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/></g><g><g><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 377px; margin-left: 112px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #475569; background-color: #FFFFFF; "><div style="display: inline-block; font-size: 11px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: light-dark(#475569, #9ba7b8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; ">origin</div></div></div></foreignObject><text x="112" y="380" fill="#475569" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="11px" text-anchor="middle" style="fill: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));">origin</text></switch></g></g></g></g></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg>
@@ -0,0 +1,23 @@
1
+ type: architecture
2
+ title: Image pipeline
3
+ groups:
4
+ aws: { label: AWS account }
5
+ nodes:
6
+ user: { label: Uploader, kind: person, icon: aws.users }
7
+ api: { label: Upload API, icon: aws.api_gateway, in: aws }
8
+ sign: { label: Presign, kind: function, icon: aws.lambda, in: aws }
9
+ bucket: { label: Raw images, kind: storage, icon: aws.s3, in: aws }
10
+ queue: { label: resize-jobs, kind: queue, icon: aws.sqs, in: aws }
11
+ resize: { label: Resizer, kind: function, icon: aws.lambda, in: aws }
12
+ table: { label: Image index, kind: database, icon: aws.dynamodb, in: aws }
13
+ cdn: { label: CDN, icon: aws.cloudfront, in: aws }
14
+ edges:
15
+ - user -> api: POST /uploads
16
+ - api -> sign: invoke
17
+ - sign -> bucket: presigned PUT
18
+ - user -> bucket: upload
19
+ - bucket -.-> queue: ObjectCreated
20
+ - queue -.-> resize: poll
21
+ - resize -> bucket: write variants
22
+ - resize -> table: index
23
+ - cdn -> bucket: origin
@@ -0,0 +1,46 @@
1
+ # Diagrams in Google Docs
2
+
3
+ Google Docs can't hold an SVG, and it strips the metadata out of images you paste in. So a diagram in a Doc is always a picture of a file that lives somewhere else. The trick is to make that somewhere else a Google Drive file that the doc can refresh from.
4
+
5
+ draw.io's Google Docs add-on does the refreshing. It inserts a `.drawio.svg` from Drive as an image, remembers which file it came from, and updates the image when the file changes. `linework publish` puts your diagrams in Drive at a fixed path, so each new version replaces the old file instead of creating a copy.
6
+
7
+ ## One-time setup
8
+
9
+ 1. Install [Google Drive for desktop](https://www.google.com/drive/download/). It syncs a local folder with your Drive, so publishing is a file copy and needs no Google login in linework.
10
+ 2. In a Google Doc, open Extensions > Add-ons > Get add-ons and install "draw.io for Docs" by JGraph.
11
+
12
+ The add-on renders diagrams through draw.io's export service at convert.diagrams.net. If your diagrams can't leave your machine, use the PNG route at the end of this page instead.
13
+
14
+ ## Put a diagram in a doc
15
+
16
+ ```bash
17
+ npx -y @itsthecsguy/linework publish docs/diagrams/checkout.drawio.svg
18
+ ```
19
+
20
+ This copies the file to `My Drive/linework/<project>/docs/diagrams/checkout.drawio.svg`. `<project>` is the git repository's folder name. With several Google accounts, or to use another synced folder, pass `--to <folder>`.
21
+
22
+ Then, in the doc: Extensions > draw.io > Insert diagrams, and pick the file. If the picker doesn't list it, look in its "All files" tab.
23
+
24
+ ## After the diagram changes
25
+
26
+ ```bash
27
+ npx -y @itsthecsguy/linework build spec.yaml -o docs/diagrams/checkout.drawio.svg # or a hand edit in draw.io
28
+ npx -y @itsthecsguy/linework publish docs/diagrams/checkout.drawio.svg
29
+ ```
30
+
31
+ Give Drive a few seconds to sync. Then, in the doc: Extensions > draw.io > Update diagrams. Every image whose file changed refreshes in place.
32
+
33
+ ## Editing from the doc
34
+
35
+ Select the diagram and choose Extensions > draw.io > Edit selected. draw.io opens the Drive file, and saving writes it back to Drive. The repo copy is now behind. Bring the edit back with:
36
+
37
+ ```bash
38
+ npx -y @itsthecsguy/linework publish --pull docs/diagrams/checkout.drawio.svg
39
+ ```
40
+
41
+ `publish` refuses to overwrite a Drive copy that someone edited after the last publish. It says so, and you choose `--pull` to take their version or `--force` to replace it.
42
+
43
+ ## Without Drive for desktop
44
+
45
+ - Upload the `.drawio.svg` at drive.google.com and insert it with the add-on as above. To update it later, use the file's Manage versions > Upload new version in Drive. Uploading it again as a new file breaks the link to the doc.
46
+ - Or skip the add-on: `npx -y @itsthecsguy/linework render docs/diagrams/checkout.drawio.svg -o checkout.png --scale 2`, insert the PNG, and put a link to the source file under it. You'll replace the image by hand when it changes.
@@ -0,0 +1,312 @@
1
+ # Linework spec reference
2
+
3
+ `npx -y @itsthecsguy/linework schema` prints the full JSON Schema.
4
+
5
+ ## Top level
6
+
7
+ | key | required | notes |
8
+ |---|---|---|
9
+ | `type` | yes | `architecture`, `flow`, `state`, `sequence` or `er` |
10
+ | `title` | no | stored in the file and used as the page name in draw.io |
11
+ | `direction` | no | `auto` (default), `TB`, `LR`, `BT` or `RL`. Not for sequence. |
12
+ | `theme` | no | the style: `clean` (default), `soft`, `dark`, `sketch`, `blueprint` or `c4` |
13
+ | `groups` | no | map of id to `{ label, in, color, highlight }`, or to a label string |
14
+ | `nodes` | yes | map of id to `{ label, kind, tech, in, icon, color, highlight }`, or to a label string |
15
+ | `edges` | no | list of edge strings, or `{ from, to, label, style, color, highlight }` objects |
16
+ | `participants` | sequence only | ordered map of id to `{ label, kind, tech }` |
17
+ | `messages` | sequence only | list of messages, notes and frames |
18
+
19
+ Unknown keys are errors, so typos surface right away.
20
+
21
+ ## Nodes
22
+
23
+ ```yaml
24
+ nodes:
25
+ api: { label: Checkout API, kind: service, tech: Go, in: vpc }
26
+ db: Orders # shorthand: just a label
27
+ cache: {} # label "Cache", default kind
28
+ ```
29
+
30
+ - `label` defaults to the id with `_`/`-` turned into spaces and the first letter capitalized.
31
+ - `kind` defaults to `service`, `step` or `state`, depending on the type.
32
+ - `in` names the group the node sits in.
33
+ - `highlight: true` draws the node in the style's accent color, solid. Use it for the one thing the doc is about.
34
+ - `color` tints it: `blue`, `violet`, `pink`, `red`, `orange`, `amber`, `green`, `teal` or `gray`. With `highlight`, it picks the highlight's color.
35
+
36
+ ## Styles
37
+
38
+ | style | looks like | font |
39
+ |---|---|---|
40
+ | `clean` | white boxes with hairline borders, groups drawn as gray grounds, cobalt accent. Nodes are neutral unless the kind means something (error, success). | IBM Plex Sans |
41
+ | `soft` | borderless pastel cards, each kind its own tint | IBM Plex Sans |
42
+ | `dark` | `clean` in GitHub's dark colors, so it sits flush on a dark README | IBM Plex Sans |
43
+ | `sketch` | hand-drawn strokes, pastel fills, red accent | Kalam (handwriting) |
44
+ | `blueprint` | light lines on deep blue, yellow accent, drafting capitals for group titles | IBM Plex Mono |
45
+ | `c4` | C4-PlantUML colors; each box says its element type | IBM Plex Sans |
46
+
47
+ The "drawn as" columns below describe `soft`. In `clean`, `dark` and `blueprint`, kinds differ by shape and dash only, and color comes from `highlight`, `color` and the error/success kinds.
48
+
49
+ Linework embeds the font, subset to the characters the diagram uses (about 10 to 15KB), so the SVG looks the same on GitHub, in a browser and in docs.
50
+
51
+ ### Architecture kinds
52
+
53
+ | kind | drawn as | use for |
54
+ |---|---|---|
55
+ | `service` | violet box | your own service, API or app server |
56
+ | `person` | pink box | a human user or role |
57
+ | `client` | blue box | browser app, mobile app, CLI |
58
+ | `function` | dashed violet box | serverless function, cron job, worker |
59
+ | `database` | green cylinder | relational or document database |
60
+ | `cache` | green box | Redis, Memcached, CDN |
61
+ | `storage` | green cylinder | object storage, file store, data lake |
62
+ | `queue` | amber pill | queue, topic, event stream |
63
+ | `external` | dashed grey box | a system you don't own |
64
+
65
+ ### Flow kinds
66
+
67
+ | kind | drawn as | use for |
68
+ |---|---|---|
69
+ | `step` | grey box | an action |
70
+ | `decision` | amber diamond | a branch; label every outgoing edge |
71
+ | `terminal` | grey pill | start or end |
72
+ | `data` | blue parallelogram | input or output data |
73
+ | `error` | red box | rejection or failure path |
74
+
75
+ ### State kinds
76
+
77
+ | kind | drawn as | use for |
78
+ |---|---|---|
79
+ | `state` | violet box | a state |
80
+ | `success` | green box | a good terminal state |
81
+ | `error` | red box | a failure state |
82
+
83
+ Write the initial and final pseudo-states as `[*]` in edges, as in Mermaid. Each `x -> [*]` gets its own end marker next to `x`.
84
+
85
+ ## Groups
86
+
87
+ ```yaml
88
+ groups:
89
+ vpc: { label: Production VPC }
90
+ data: { label: Data tier, in: vpc } # nested
91
+ ```
92
+
93
+ Edges connect nodes, not groups. To show "the API talks to the data tier", connect to the specific store.
94
+
95
+ ## Edges
96
+
97
+ ```yaml
98
+ edges:
99
+ - a -> b # call / flow
100
+ - a -> b: HTTPS # with label
101
+ - a ==> b: HTTPS # highlighted (accent color, thicker)
102
+ - a -.-> b: OrderPlaced # async or event (dashed)
103
+ - a <-> b: sync # two-way
104
+ - a -- b # association, no arrowhead
105
+ - "[*] -> pending" # state pseudo-state; quote lines starting with [
106
+ - "a -> b: label: with colon"
107
+ ```
108
+
109
+ For a colored edge, or a highlighted one that isn't a plain call, use the object form:
110
+
111
+ ```yaml
112
+ - { from: api, to: dlq, label: on failure, style: async, color: red }
113
+ - { from: a, to: b, style: bidir, highlight: true }
114
+ ```
115
+
116
+ The arrow needs a space on each side. Repeated edges between the same two nodes are allowed and get separate ids.
117
+
118
+ ## Full examples
119
+
120
+ ### Architecture
121
+
122
+ ```yaml
123
+ type: architecture
124
+ title: Checkout
125
+ groups:
126
+ vpc: { label: Production VPC }
127
+ data: { label: Data tier, in: vpc }
128
+ nodes:
129
+ user: { label: Shopper, kind: person }
130
+ web: { label: Web app, kind: client, tech: Next.js }
131
+ gw: { label: API gateway, tech: Envoy, in: vpc }
132
+ api: { label: Checkout API, tech: Go, in: vpc }
133
+ worker: { label: Fulfillment worker, tech: Go, in: vpc }
134
+ queue: { label: order-events, kind: queue, tech: Kafka, in: vpc }
135
+ db: { label: Orders, kind: database, tech: Postgres, in: data }
136
+ cache: { label: Session cache, kind: cache, tech: Redis, in: data }
137
+ stripe: { kind: external, tech: Payments API }
138
+ email: { label: SendGrid, kind: external, tech: Email }
139
+ edges:
140
+ - user -> web: browses
141
+ - web -> gw: HTTPS
142
+ - gw -> api: gRPC
143
+ - api -> cache: read session
144
+ - api -> db: SQL
145
+ - api -> stripe: charge
146
+ - api -.-> queue: OrderPlaced
147
+ - queue -.-> worker: consume
148
+ - worker -> db: update status
149
+ - worker -> email: receipt
150
+ ```
151
+
152
+ ### Flow
153
+
154
+ ```yaml
155
+ type: flow
156
+ title: Refund request
157
+ nodes:
158
+ start: { label: Refund requested, kind: terminal }
159
+ lookup: { label: Look up order }
160
+ window: { label: Within 30 days?, kind: decision }
161
+ amount: { label: Over $500?, kind: decision }
162
+ auto: { label: Auto-approve }
163
+ review: { label: Queue for manual review }
164
+ approved: { label: Approved?, kind: decision }
165
+ refund: { label: Issue refund via Stripe }
166
+ notify: { label: Email customer }
167
+ deny: { label: Deny with reason, kind: error }
168
+ done: { label: Done, kind: terminal }
169
+ edges:
170
+ - start -> lookup
171
+ - lookup -> window
172
+ - window -> amount: "yes"
173
+ - window -> deny: "no"
174
+ - amount -> auto: "no"
175
+ - amount -> review: "yes"
176
+ - review -> approved
177
+ - approved -> refund: "yes"
178
+ - approved -> deny: "no"
179
+ - auto -> refund
180
+ - refund -> notify
181
+ - deny -> notify
182
+ - notify -> done
183
+ ```
184
+
185
+ ### State
186
+
187
+ ```yaml
188
+ type: state
189
+ title: Payment lifecycle
190
+ nodes:
191
+ created: {}
192
+ authorizing: {}
193
+ authorized: {}
194
+ captured: { kind: success }
195
+ failed: { kind: error }
196
+ voided: {}
197
+ refunded: {}
198
+ edges:
199
+ - "[*] -> created"
200
+ - created -> authorizing: submit
201
+ - authorizing -> authorized: approved
202
+ - authorizing -> failed: declined
203
+ - authorized -> captured: capture
204
+ - authorized -> voided: void
205
+ - captured -> refunded: refund
206
+ - failed -> created: retry
207
+ - "captured -> [*]"
208
+ - "voided -> [*]"
209
+ - "refunded -> [*]"
210
+ ```
211
+
212
+ ## Icons (architecture)
213
+
214
+ ```yaml
215
+ nodes:
216
+ fn: { label: Resizer, kind: function, icon: aws.lambda }
217
+ run: { label: API, icon: gcp.cloud_run }
218
+ pod: { label: Worker pods, icon: k8s.deploy }
219
+ ```
220
+
221
+ `linework icons aws` lists every AWS name (about 1,000); add a filter word to search. Common short names work too: `aws.s3`, `aws.sqs`, `aws.kms`, `aws.msk`, `gcp.pubsub`, `gcp.gke`, `k8s.service`, `k8s.ingress`. An unknown name is a warning, and the node is drawn without an icon.
222
+
223
+ ## Sequence
224
+
225
+ ```yaml
226
+ type: sequence
227
+ title: Card payment
228
+ participants:
229
+ user: { label: Shopper, kind: person }
230
+ web: { label: Web app, kind: client }
231
+ api: { label: Checkout API }
232
+ stripe: { kind: external }
233
+ db: { label: Orders DB, kind: database }
234
+ messages:
235
+ - user -> web: Click "Pay"
236
+ - web -> api: POST /checkout
237
+ - api -> db: insert order (pending)
238
+ - db --> api: order id
239
+ - api -> stripe: create PaymentIntent
240
+ - stripe --> api: client_secret
241
+ - api --> web: client_secret
242
+ - web -> stripe: confirmCardPayment
243
+ - alt:
244
+ - when: succeeded
245
+ do:
246
+ - stripe -.-> api: webhook payment_succeeded
247
+ - api -> db: mark paid
248
+ - note over api, db: idempotent on event id
249
+ - when: declined
250
+ do:
251
+ - stripe --> web: card_declined
252
+ - web -> web: show error
253
+ - web --> user: result page
254
+ ```
255
+
256
+ | item | form |
257
+ |---|---|
258
+ | call | `a -> b: text` |
259
+ | highlighted call | `a ==> b: text` (accent color) |
260
+ | reply | `b --> a: text` (dashed, open arrow) |
261
+ | async | `a -.-> b: text` (open arrow) |
262
+ | self call | `a -> a: text` |
263
+ | note | `note over a: text`, `note over a, b: text`, `note left of a: text`, `note right of a: text` |
264
+ | branches | `- alt:` or `- par:` with a list of `{ when: condition, do: [items] }` |
265
+ | block | `- loop: label`, `- opt: label`, `- critical: label` or `- break: label`, each with `do: [items]` |
266
+
267
+ Frames nest. Keep it to 6 participants or fewer, so it fits a page.
268
+
269
+ ## ER
270
+
271
+ ```yaml
272
+ type: er
273
+ title: Billing schema
274
+ nodes:
275
+ orgs:
276
+ label: organizations
277
+ fields:
278
+ - id: uuid pk
279
+ - name: text
280
+ users:
281
+ fields:
282
+ - id: uuid pk
283
+ - org_id: uuid fk
284
+ - email: text unique
285
+ invoices:
286
+ fields:
287
+ - id: uuid pk
288
+ - org_id: uuid fk
289
+ - paid_at: timestamptz null
290
+ edges:
291
+ - users }o--|| orgs: belongs to
292
+ - invoices }o--|| orgs: billed to
293
+ ```
294
+
295
+ A field is `name: type flags`, a plain string `"name type flags"`, or `{ name, type, flags: [...] }`. Flags: `pk`, `fk`, `unique`, `null`. Kinds: `entity` (default), `view` (dashed) and `external` (a table another system owns).
296
+
297
+ Relationships use Mermaid's crow's-foot notation:
298
+
299
+ | left end | right end | means |
300
+ |---|---|---|
301
+ | `\|\|` | `\|\|` | exactly one |
302
+ | `\|o` | `o\|` | zero or one |
303
+ | `}o` | `o{` | zero or more |
304
+ | `}\|` | `\|{` | one or more |
305
+
306
+ The middle is `--` for an identifying relationship (solid line) or `..` for a non-identifying one (dashed).
307
+
308
+ ## Importing Mermaid
309
+
310
+ `linework import file.mmd` prints an linework spec. `-o out.drawio.svg` builds it straight away. A Markdown file works too; use `--block N` when it has several Mermaid blocks. Supported: `flowchart`/`graph`, `stateDiagram`, `sequenceDiagram`, `erDiagram`.
311
+
312
+ A flowchart with diamonds becomes a `flow`. One with subgraphs or cylinders becomes an `architecture` diagram. In that case a `<br>` second line becomes `tech`, and kinds are guessed from shapes and names: a cylinder becomes a database, "Kafka" becomes a queue, "Stripe" becomes external. Mermaid styling (`classDef`, `style`, `click`) is dropped. Review the printed spec before building, and fix any kinds it guessed wrong.
@@ -0,0 +1,53 @@
1
+ # What makes a good design-doc diagram
2
+
3
+ Linework handles the layout and the look. These rules are about content, which is the part only you can get right.
4
+
5
+ ## Scope
6
+
7
+ - **One diagram makes one point.** "How a checkout request flows" is a diagram. "Everything in the payments org" is a wiki page. When you need both the overview and the detail, draw two diagrams.
8
+ - **Aim for 12 nodes or fewer.** Past about 15, readers stop following edges. `build` warns at 20.
9
+ - **Pick a level of zoom and stay there.** Don't put "Kubernetes cluster" next to "parseOrder()" in the same diagram.
10
+ - **Leave out what the reader doesn't need.** Logging, metrics and auth sidecars can usually go unless the doc is about them.
11
+
12
+ ## Naming
13
+
14
+ - Label nodes with the same words the doc text uses. If the prose says "Checkout API", don't label the node "checkout-svc".
15
+ - Use `tech` for the technology (`Postgres`, `Kafka`, `Go`), not for a description.
16
+ - Keep labels to about 3 words. A label that wraps to a third line means the node is doing too much.
17
+
18
+ ## Edges
19
+
20
+ - **Label edges in architecture diagrams with the protocol or the verb**: `HTTPS`, `gRPC`, `SQL`, `publishes OrderPlaced`, `reads session`. An unlabeled arrow makes the reader guess.
21
+ - **Use `-.->` for async**: events, queues, webhooks, fire-and-forget. Readers rely on the solid/dashed distinction to see where latency and failure modes change.
22
+ - **Point the arrow the way the request goes**, not the way data comes back. Only show a return edge when the reply is interesting.
23
+ - **Label every edge out of a decision** in a flow (`yes`/`no`, or the condition).
24
+ - In state diagrams, label transitions with the event that triggers them (`payment_succeeded`), not the resulting state.
25
+
26
+ ## Groups
27
+
28
+ - **Draw groups along a real boundary**: a network (VPC), a trust boundary, a deployment unit or an owning team. Say which in the label, e.g. "Production VPC" or "Payments team".
29
+ - **Don't group just to tidy up.** Every box reads as a claim about how the system is structured.
30
+ - Keep external systems (`kind: external`) outside your groups.
31
+
32
+ ## Color and emphasis
33
+
34
+ - **Start neutral.** The default style draws every node the same, so whatever you color stands out. Add color only when it tells the reader something.
35
+ - **Highlight one thing.** Put `highlight: true` on the component the section is about and `==>` on the 2 or 3 edges that make up its path. A reader's eye goes there first. If everything is highlighted, nothing is.
36
+ - **Color marks a category, and the doc says which.** Red for failure paths, green for what this proposal adds, gray for what's being removed. Write one sentence under the diagram that explains it, e.g. "New components are green."
37
+ - **Use at most 2 or 3 colors** besides the highlight. More turns color back into noise.
38
+ - **Keep error and success kinds for real errors and successes.** They're red and green in every style.
39
+ - **Pick the style for the medium**: `clean` for docs and READMEs, `dark` for dark-mode pages, `soft` for slides, `sketch` for early drafts, `blueprint` for technical deep dives. Use one style across all the diagrams in a doc.
40
+
41
+ ## Direction
42
+
43
+ - Leave out `direction` on the first build. `auto` tries both and keeps the one that fits a doc page, which is about 800px wide.
44
+ - Set it only after looking at the result, and only if it reads wrong. A short linear pipeline of 5 or fewer steps can read better as LR.
45
+ - Don't force LR on a diagram with more than about 6 nodes in a row. It comes out 1,500px or more wide, and embedded in a doc its text shrinks to unreadable. `check` warns about this as `too-wide`.
46
+
47
+ ## Checking your result
48
+
49
+ Look at the PNG and ask:
50
+ 1. Could someone who hasn't read the doc say what this diagram shows in one sentence?
51
+ 2. Does every node appear in the doc text, or matter to the point?
52
+ 3. Does every edge say what goes across it?
53
+ 4. Is anything here only because "it exists", not because it matters to the point?