@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.
- package/LICENSE +21 -0
- package/NOTICE +11 -0
- package/README.md +164 -2
- package/assets/drawio/LICENSE +201 -0
- package/assets/drawio/VERSION +1 -0
- package/assets/drawio/favicon.ico +0 -0
- package/assets/drawio/images/1x1.png +0 -0
- package/assets/drawio/images/2x2.png +0 -0
- package/assets/drawio/images/3x3.png +0 -0
- package/assets/drawio/images/ajax-loader.gif +0 -0
- package/assets/drawio/images/android-chrome-512x512.png +0 -0
- package/assets/drawio/images/apple-touch-icon.png +0 -0
- package/assets/drawio/images/aui-wait.gif +0 -0
- package/assets/drawio/images/broken.png +0 -0
- package/assets/drawio/images/browserconfig.xml +9 -0
- package/assets/drawio/images/close.png +0 -0
- package/assets/drawio/images/cloud-connector-atlas.png +0 -0
- package/assets/drawio/images/collapsed.gif +0 -0
- package/assets/drawio/images/delete.png +0 -0
- package/assets/drawio/images/document-google-drive-icon-80.png +0 -0
- package/assets/drawio/images/draw-search.png +0 -0
- package/assets/drawio/images/drawio.svg +19 -0
- package/assets/drawio/images/drawlogo-color.svg +50 -0
- package/assets/drawio/images/drawlogo-gray.svg +18 -0
- package/assets/drawio/images/drawlogo-text-bottom.svg +75 -0
- package/assets/drawio/images/drawlogo.svg +18 -0
- package/assets/drawio/images/drawlogo128.png +0 -0
- package/assets/drawio/images/drawlogo144.png +0 -0
- package/assets/drawio/images/drawlogo256.png +0 -0
- package/assets/drawio/images/drawlogo48-gray.png +0 -0
- package/assets/drawio/images/drawlogo48.png +0 -0
- package/assets/drawio/images/drawlogo80.png +0 -0
- package/assets/drawio/images/droptarget.png +0 -0
- package/assets/drawio/images/edit.gif +0 -0
- package/assets/drawio/images/edit16.png +0 -0
- package/assets/drawio/images/edit32.png +0 -0
- package/assets/drawio/images/edit80.png +0 -0
- package/assets/drawio/images/embed-icon.png +0 -0
- package/assets/drawio/images/expanded.gif +0 -0
- package/assets/drawio/images/facebook.png +0 -0
- package/assets/drawio/images/favicon-16x16.png +0 -0
- package/assets/drawio/images/favicon-32x32.png +0 -0
- package/assets/drawio/images/file.png +0 -0
- package/assets/drawio/images/folder.png +0 -0
- package/assets/drawio/images/gadget-screenshot.png +0 -0
- package/assets/drawio/images/gadget-thumb.png +0 -0
- package/assets/drawio/images/github-logo-white.svg +6 -0
- package/assets/drawio/images/github-logo.svg +17 -0
- package/assets/drawio/images/gitlab-logo-white.svg +1 -0
- package/assets/drawio/images/gitlab-logo.svg +1 -0
- package/assets/drawio/images/glyphicons_blogger.png +0 -0
- package/assets/drawio/images/glyphicons_facebook.png +0 -0
- package/assets/drawio/images/glyphicons_github.png +0 -0
- package/assets/drawio/images/glyphicons_google.png +0 -0
- package/assets/drawio/images/glyphicons_star.png +0 -0
- package/assets/drawio/images/glyphicons_twitter.png +0 -0
- package/assets/drawio/images/glyphicons_youtube.png +0 -0
- package/assets/drawio/images/google-drive-connector-atlas.png +0 -0
- package/assets/drawio/images/google-drive-connector-atlas.svg +121 -0
- package/assets/drawio/images/google-drive-logo-white.svg +9 -0
- package/assets/drawio/images/google-drive-logo.svg +17 -0
- package/assets/drawio/images/google-share.png +0 -0
- package/assets/drawio/images/icon-192-maskable.png +0 -0
- package/assets/drawio/images/icon-192.png +0 -0
- package/assets/drawio/images/icon-512-maskable.png +0 -0
- package/assets/drawio/images/icon-512.png +0 -0
- package/assets/drawio/images/icon-search.svg +21 -0
- package/assets/drawio/images/img-hi-res.png +0 -0
- package/assets/drawio/images/img-lo-res.png +0 -0
- package/assets/drawio/images/list.svg +16 -0
- package/assets/drawio/images/locked.png +0 -0
- package/assets/drawio/images/log.png +0 -0
- package/assets/drawio/images/logo-confluence.png +0 -0
- package/assets/drawio/images/logo-flat-small.png +0 -0
- package/assets/drawio/images/logo-flat.png +0 -0
- package/assets/drawio/images/logo-jira.png +0 -0
- package/assets/drawio/images/logo-small.gif +0 -0
- package/assets/drawio/images/logo-white.png +0 -0
- package/assets/drawio/images/logo.png +0 -0
- package/assets/drawio/images/manifest.json +25 -0
- package/assets/drawio/images/move.png +0 -0
- package/assets/drawio/images/notion-logo-white.svg +1 -0
- package/assets/drawio/images/notion-logo.svg +1 -0
- package/assets/drawio/images/onedrive-connector-atlas.png +0 -0
- package/assets/drawio/images/onedrive-connector-atlas.svg +248 -0
- package/assets/drawio/images/onedrive-logo-white.svg +29 -0
- package/assets/drawio/images/onedrive-logo.svg +29 -0
- package/assets/drawio/images/osa_database.png +0 -0
- package/assets/drawio/images/osa_drive-harddisk.png +0 -0
- package/assets/drawio/images/plant-uml-atlas.png +0 -0
- package/assets/drawio/images/samepage-icon-color.svg +37 -0
- package/assets/drawio/images/save.png +0 -0
- package/assets/drawio/images/sidebar-android.png +0 -0
- package/assets/drawio/images/sidebar-archimate.png +0 -0
- package/assets/drawio/images/sidebar-arrows.png +0 -0
- package/assets/drawio/images/sidebar-arrows2.png +0 -0
- package/assets/drawio/images/sidebar-basic.png +0 -0
- package/assets/drawio/images/sidebar-c4.png +0 -0
- package/assets/drawio/images/sidebar-cabinets.png +0 -0
- package/assets/drawio/images/sidebar-cumulus.png +0 -0
- package/assets/drawio/images/sidebar-dfd.png +0 -0
- package/assets/drawio/images/sidebar-dynamics365.png +0 -0
- package/assets/drawio/images/sidebar-eip.png +0 -0
- package/assets/drawio/images/sidebar-er.png +0 -0
- package/assets/drawio/images/sidebar-floorplans.png +0 -0
- package/assets/drawio/images/sidebar-flowchart.png +0 -0
- package/assets/drawio/images/sidebar-gcp3.png +0 -0
- package/assets/drawio/images/sidebar-general.png +0 -0
- package/assets/drawio/images/sidebar-kubernetes.png +0 -0
- package/assets/drawio/images/sidebar-leanmapping.png +0 -0
- package/assets/drawio/images/sidebar-mockups.png +0 -0
- package/assets/drawio/images/sidebar-network.png +0 -0
- package/assets/drawio/images/sidebar-network2.png +0 -0
- package/assets/drawio/images/sidebar-openstack.png +0 -0
- package/assets/drawio/images/sidebar-sitemap.png +0 -0
- package/assets/drawio/images/sidebar-threatmodeling.png +0 -0
- package/assets/drawio/images/sidebar-uml.png +0 -0
- package/assets/drawio/images/sketch-logo128.png +0 -0
- package/assets/drawio/images/spin.gif +0 -0
- package/assets/drawio/images/sprites.png +0 -0
- package/assets/drawio/images/stop-flat-icon-80.png +0 -0
- package/assets/drawio/images/submenu.gif +0 -0
- package/assets/drawio/images/touch-submenu.png +0 -0
- package/assets/drawio/images/transparent.gif +0 -0
- package/assets/drawio/images/trello-logo-white-orange.svg +6 -0
- package/assets/drawio/images/trello-logo-white.svg +6 -0
- package/assets/drawio/images/trello-logo.svg +1 -0
- package/assets/drawio/images/tweet.png +0 -0
- package/assets/drawio/images/update16.png +0 -0
- package/assets/drawio/images/update32.png +0 -0
- package/assets/drawio/images/update80.png +0 -0
- package/assets/drawio/images/youtube.png +0 -0
- package/assets/drawio/img/clipart/Battery_0_128x128.png +0 -0
- package/assets/drawio/img/clipart/Battery_100_128x128.png +0 -0
- package/assets/drawio/img/clipart/Battery_50_128x128.png +0 -0
- package/assets/drawio/img/clipart/Battery_75_128x128.png +0 -0
- package/assets/drawio/img/clipart/Battery_allstates_128x128.png +0 -0
- package/assets/drawio/img/clipart/Bluetooth_128x128.png +0 -0
- package/assets/drawio/img/clipart/Earth_globe_128x128.png +0 -0
- package/assets/drawio/img/clipart/Empty_Folder_128x128.png +0 -0
- package/assets/drawio/img/clipart/Full_Folder_128x128.png +0 -0
- package/assets/drawio/img/clipart/Gear_128x128.png +0 -0
- package/assets/drawio/img/clipart/Keys_128x128.png +0 -0
- package/assets/drawio/img/clipart/Lock_128x128.png +0 -0
- package/assets/drawio/img/clipart/Mouse_Pointer_128x128.png +0 -0
- package/assets/drawio/img/clipart/Plug_128x128.png +0 -0
- package/assets/drawio/img/clipart/Ships_Wheel_128x128.png +0 -0
- package/assets/drawio/img/clipart/Star_128x128.png +0 -0
- package/assets/drawio/img/clipart/Tire_128x128.png +0 -0
- package/assets/drawio/index.html +92 -0
- package/assets/drawio/js/PostConfig.js +7 -0
- package/assets/drawio/js/PreConfig.js +13 -0
- package/assets/drawio/js/app.min.js +18466 -0
- package/assets/drawio/js/bootstrap.js +428 -0
- package/assets/drawio/js/diagramly/LibavoidRouting.js +4459 -0
- package/assets/drawio/js/export-init.js +21 -0
- package/assets/drawio/js/extensions.min.js +10478 -0
- package/assets/drawio/js/libavoid-js/LICENSE +505 -0
- package/assets/drawio/js/libavoid-js/libavoid-routing.js +1633 -0
- package/assets/drawio/js/libavoid-js/libavoid.min.js +59 -0
- package/assets/drawio/js/main.js +22 -0
- package/assets/drawio/js/rough/rough.min.js +1 -0
- package/assets/drawio/js/shapes-14-6-5.min.js +3457 -0
- package/assets/drawio/js/stencils.min.js +447 -0
- package/assets/drawio/mxgraph/css/common.css +147 -0
- package/assets/drawio/resources/dia.txt +2901 -0
- package/assets/drawio/styles/dark-default.xml +109 -0
- package/assets/drawio/styles/default-old.xml +109 -0
- package/assets/drawio/styles/default.xml +203 -0
- package/assets/drawio/styles/fonts/ArchitectsDaughter-Regular.ttf +0 -0
- package/assets/drawio/styles/grapheditor.css +4501 -0
- package/assets/drawio/styles/high-contrast.css +128 -0
- package/assets/drawio/styles/thumb_horz.png +0 -0
- package/assets/drawio/styles/thumb_vertical.png +0 -0
- package/assets/fonts/ibm-plex-mono-LICENSE.txt +93 -0
- package/assets/fonts/ibm-plex-sans-LICENSE.txt +93 -0
- package/assets/fonts/kalam-400.woff2 +0 -0
- package/assets/fonts/kalam-700.woff2 +0 -0
- package/assets/fonts/kalam-LICENSE.txt +93 -0
- package/assets/fonts/plex-mono-400.woff2 +0 -0
- package/assets/fonts/plex-mono-600.woff2 +0 -0
- package/assets/fonts/plex-sans-400.woff2 +0 -0
- package/assets/fonts/plex-sans-600.woff2 +0 -0
- package/dist/api.js +181 -0
- package/dist/cli.js +262 -0
- package/dist/drawio/icons.js +121 -0
- package/dist/drawio/merge.js +309 -0
- package/dist/drawio/read.js +180 -0
- package/dist/drawio/show.js +501 -0
- package/dist/drawio/theme.js +425 -0
- package/dist/drawio/write.js +300 -0
- package/dist/edit/server.js +212 -0
- package/dist/git.js +46 -0
- package/dist/import/mermaid.js +569 -0
- package/dist/layout/layout.js +212 -0
- package/dist/layout/sequence.js +333 -0
- package/dist/layout/text.js +73 -0
- package/dist/lint/check.js +184 -0
- package/dist/lint/fixlabels.js +128 -0
- package/dist/mcp/server.js +239 -0
- package/dist/publish.js +121 -0
- package/dist/render/browser.js +210 -0
- package/dist/render/fonts.js +66 -0
- package/dist/report.js +36 -0
- package/dist/spec/model.js +53 -0
- package/dist/spec/parse.js +497 -0
- package/package.json +71 -4
- package/skills/linework/SKILL.md +214 -0
- package/skills/linework/examples/billing-er.drawio.svg +4 -0
- package/skills/linework/examples/billing-er.yaml +31 -0
- package/skills/linework/examples/checkout.drawio.svg +4 -0
- package/skills/linework/examples/checkout.yaml +28 -0
- package/skills/linework/examples/pay-sequence.drawio.svg +4 -0
- package/skills/linework/examples/pay-sequence.yaml +28 -0
- package/skills/linework/examples/payment-state.drawio.svg +4 -0
- package/skills/linework/examples/payment-state.yaml +22 -0
- package/skills/linework/examples/refund-flow.drawio.svg +4 -0
- package/skills/linework/examples/refund-flow.yaml +29 -0
- package/skills/linework/examples/serverless-aws.drawio.svg +4 -0
- package/skills/linework/examples/serverless-aws.yaml +23 -0
- package/skills/linework/references/google-docs.md +46 -0
- package/skills/linework/references/spec.md +312 -0
- package/skills/linework/references/style-guide.md +53 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: linework
|
|
3
|
+
description: Create and edit software diagrams (architecture, flowcharts, state machines, sequence diagrams, ER/database schemas) as .drawio.svg files that render in Markdown, HTML and GitHub, and that people can open and edit by hand in draw.io. Use when a design doc, README or ADR needs a diagram, or when asked to change an existing .drawio.svg.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Linework
|
|
7
|
+
|
|
8
|
+
You describe the diagram as a small YAML spec. `linework` does the layout, styling and rendering, and writes a `.drawio.svg`. That's a normal SVG for docs, with the editable draw.io model embedded inside it. Never write coordinates, SVG or draw.io XML yourself.
|
|
9
|
+
|
|
10
|
+
Run it as `npx -y @itsthecsguy/linework` unless `linework` is already on PATH. The first run needs a Chromium-based browser. If it says none was found, run `npx playwright install chromium`.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
1. **Decide what the diagram is for.** One diagram makes one point. Pick the type:
|
|
15
|
+
- `architecture`: components and how they talk. Services, data stores, queues, external systems, trust boundaries.
|
|
16
|
+
- `flow`: a process with steps and decisions.
|
|
17
|
+
- `state`: the lifecycle of one thing, like an order, payment or job.
|
|
18
|
+
- `sequence`: who calls whom, in what order, for one scenario.
|
|
19
|
+
- `er`: database tables, their columns and how they relate.
|
|
20
|
+
|
|
21
|
+
If the doc already has a Mermaid diagram, convert it instead of rewriting it: `npx -y @itsthecsguy/linework import doc.md --block 1 -o docs/diagrams/x.drawio.svg`.
|
|
22
|
+
2. **Write the spec** to a scratch file, or pipe it on stdin. The `.drawio.svg` is the source of truth, so you don't need to keep the YAML.
|
|
23
|
+
3. **Build with a preview:**
|
|
24
|
+
```bash
|
|
25
|
+
npx -y @itsthecsguy/linework build spec.yaml -o docs/diagrams/checkout.drawio.svg --png /tmp/checkout.png
|
|
26
|
+
```
|
|
27
|
+
4. **Read the output.** `spec error` lines tell you exactly what to fix. `check:` lists layout problems. Fix every `error` and the warnings that matter, then rebuild.
|
|
28
|
+
5. **Look at the PNG** if you can view images. Check that the diagram tells the story you meant, flows in a sensible direction and doesn't sprawl. If `check` says `too-wide`, remove `direction` (or set `TB`) or split it.
|
|
29
|
+
6. **Embed the `.drawio.svg`**, never the PNG (see "Putting it in a doc").
|
|
30
|
+
|
|
31
|
+
## Spec
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
type: architecture # architecture | flow | state | sequence | er
|
|
35
|
+
title: Checkout # optional
|
|
36
|
+
direction: auto # auto (default) | TB | LR | BT | RL
|
|
37
|
+
theme: clean # clean (default) | soft | dark | sketch | blueprint | c4
|
|
38
|
+
groups: # optional boxes around nodes; can nest with `in`
|
|
39
|
+
vpc: { label: Production VPC }
|
|
40
|
+
data: { label: Data tier, in: vpc }
|
|
41
|
+
nodes: # id: { label, kind, tech, in } (all optional)
|
|
42
|
+
user: { label: Shopper, kind: person }
|
|
43
|
+
web: { label: Web app, kind: client, tech: Next.js }
|
|
44
|
+
api: { label: Checkout API, tech: Go, in: vpc, highlight: true }
|
|
45
|
+
queue: { label: order-events, kind: queue, tech: Kafka, in: vpc }
|
|
46
|
+
db: { label: Orders, kind: database, tech: Postgres, in: data }
|
|
47
|
+
stripe: { kind: external, tech: Payments API } # label defaults to "Stripe"
|
|
48
|
+
edges: # "from ARROW to: label"
|
|
49
|
+
- user -> web
|
|
50
|
+
- web ==> api: HTTPS # ==> highlighted: the path the doc is about
|
|
51
|
+
- api -> db: SQL
|
|
52
|
+
- api -.-> queue: OrderPlaced # -.-> async/event, dashed
|
|
53
|
+
- api -> stripe: charge
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- Ids use letters, digits, `_`, `.` and `-`. The label defaults to the id with its first letter capitalized.
|
|
57
|
+
- Arrows: `->` call or flow, `==>` the same but highlighted, `-.->` async or event, `<->` two-way, `--` no arrowhead. Put spaces around the arrow.
|
|
58
|
+
- `tech` is the small, quieter second line. Use it for the technology, not a description.
|
|
59
|
+
- Node order matters a little. Layout tries to keep the declaration order, so list nodes roughly in reading order.
|
|
60
|
+
- Quote an edge if its label contains `: ` or `#`, for example `- "api -> db: SELECT: orders"`.
|
|
61
|
+
- Architecture nodes can carry a cloud icon: `icon: aws.lambda`, `gcp.cloud_run`, `k8s.pod`, `azure.<name>`. Run `npx -y @itsthecsguy/linework icons aws lambda` to search names. Use icons when the doc is about a specific cloud; leave them off for logical diagrams.
|
|
62
|
+
- Styles (`theme:`): use `clean` unless asked. It's minimal: white boxes, hairline borders, groups as gray grounds, IBM Plex Sans, and color only where it means something.
|
|
63
|
+
- `soft`: borderless pastel cards, tinted by kind. For slides and docs that want color coding.
|
|
64
|
+
- `dark`: for dark-mode docs and slides.
|
|
65
|
+
- `sketch`: hand-drawn lines and handwriting. For early proposals ("this is a draft") and whiteboard-style explainers.
|
|
66
|
+
- `blueprint`: light lines on deep blue, monospace. For technical deep dives that want a distinct look.
|
|
67
|
+
- `c4`: C4-model conventions; labels each box with its element type.
|
|
68
|
+
- Color is for meaning, so most nodes stay neutral:
|
|
69
|
+
- `highlight: true` on a node, group or participant, or `==>` on an edge or message, makes it the first thing a reader sees. Highlight the one path or component the surrounding text is about: often one node and the 2 or 3 edges into and out of it. `build` warns when you highlight so much that nothing stands out.
|
|
70
|
+
- `color: <name>` tints a node, group or edge to mark a category, like red for failure paths or green for what's new in this proposal. Say what the color means in the doc text. Names: `blue`, `violet`, `pink`, `red`, `orange`, `amber`, `green`, `teal`, `gray`.
|
|
71
|
+
- Kinds `error` and `success` are red and green in every style.
|
|
72
|
+
- An edge with a color uses the object form: `- { from: api, to: dlq, label: on failure, style: async, color: red }`.
|
|
73
|
+
|
|
74
|
+
Node kinds, also listed by `linework kinds`:
|
|
75
|
+
|
|
76
|
+
| type | kinds (default first) |
|
|
77
|
+
|---|---|
|
|
78
|
+
| architecture | `service`, `person`, `client`, `function`, `database`, `cache`, `storage`, `queue`, `external` |
|
|
79
|
+
| flow | `step`, `decision`, `terminal`, `data`, `error` |
|
|
80
|
+
| state | `state`, `success`, `error` (start and end come from `[*]`) |
|
|
81
|
+
| sequence | `service`, `person`, `client`, `function`, `database`, `queue`, `external` |
|
|
82
|
+
| er | `entity`, `view`, `external` |
|
|
83
|
+
|
|
84
|
+
Flow and state specifics:
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
type: flow
|
|
88
|
+
nodes:
|
|
89
|
+
start: { label: Refund requested, kind: terminal }
|
|
90
|
+
window: { label: Within 30 days?, kind: decision }
|
|
91
|
+
refund: { label: Issue refund }
|
|
92
|
+
deny: { label: Deny with reason, kind: error }
|
|
93
|
+
edges:
|
|
94
|
+
- start -> window
|
|
95
|
+
- window -> refund: "yes" # label every edge leaving a decision
|
|
96
|
+
- window -> deny: "no"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```yaml
|
|
100
|
+
type: state
|
|
101
|
+
nodes:
|
|
102
|
+
pending: {}
|
|
103
|
+
paid: { kind: success }
|
|
104
|
+
failed: { kind: error }
|
|
105
|
+
edges:
|
|
106
|
+
- "[*] -> pending" # quote edges that use [*]
|
|
107
|
+
- pending -> paid: payment_succeeded
|
|
108
|
+
- pending -> failed: declined
|
|
109
|
+
- "paid -> [*]"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Sequence diagrams use `participants` (in left-to-right order) and `messages`:
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
type: sequence
|
|
116
|
+
participants:
|
|
117
|
+
web: { label: Web app, kind: client }
|
|
118
|
+
api: { label: Checkout API }
|
|
119
|
+
stripe: { kind: external }
|
|
120
|
+
messages:
|
|
121
|
+
- web ==> api: POST /checkout # -> call; ==> highlighted call
|
|
122
|
+
- api -> stripe: create PaymentIntent
|
|
123
|
+
- stripe --> api: client_secret # --> reply (dashed)
|
|
124
|
+
- api --> web: 200 OK
|
|
125
|
+
- note over api, stripe: retried with an idempotency key
|
|
126
|
+
- alt: # alt and par take branches
|
|
127
|
+
- when: payment succeeded
|
|
128
|
+
do:
|
|
129
|
+
- stripe -.-> api: webhook # -.-> async
|
|
130
|
+
- when: declined
|
|
131
|
+
do:
|
|
132
|
+
- api --> web: 402
|
|
133
|
+
- loop: every 30s # loop, opt, critical, break take one block
|
|
134
|
+
do:
|
|
135
|
+
- web -> api: poll status
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Activation bars come from call/reply pairs automatically: each `a -> b` closed by a later `b --> a`. Participants take `color` and `highlight` like nodes.
|
|
139
|
+
|
|
140
|
+
ER diagrams put `fields` on nodes and use Mermaid's crow's-foot notation for edges:
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
type: er
|
|
144
|
+
nodes:
|
|
145
|
+
users:
|
|
146
|
+
fields:
|
|
147
|
+
- id: uuid pk
|
|
148
|
+
- org_id: uuid fk
|
|
149
|
+
- email: text unique
|
|
150
|
+
orgs:
|
|
151
|
+
label: organizations
|
|
152
|
+
fields: [ "id: uuid pk", "name: text" ]
|
|
153
|
+
edges:
|
|
154
|
+
- users }o--|| orgs: belongs to # many users to exactly one org
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Field flags: `pk`, `fk`, `unique`, `null`. Cardinality ends: `||` one, `|o` zero or one, `}o` / `o{` many, `}|` / `|{` one or many. Use `--` for identifying relationships, `..` for the rest.
|
|
158
|
+
|
|
159
|
+
More examples and rules are in `references/spec.md`. Read `references/style-guide.md` before drawing anything non-trivial.
|
|
160
|
+
|
|
161
|
+
## Editing an existing diagram
|
|
162
|
+
|
|
163
|
+
Always start from the file, never from an old copy of the spec:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npx -y @itsthecsguy/linework show docs/diagrams/checkout.drawio.svg > /tmp/spec.yaml # current spec, hand edits included
|
|
167
|
+
# edit /tmp/spec.yaml; keep the "# linework-base:" line at the top
|
|
168
|
+
npx -y @itsthecsguy/linework build /tmp/spec.yaml -o docs/diagrams/checkout.drawio.svg --png /tmp/checkout.png
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
If someone has arranged the diagram by hand in draw.io, `build` merges your changes into their layout instead of starting over. (For sequence diagrams, hand-placed lifeline columns stay; rows always follow message order.)
|
|
172
|
+
- Existing nodes stay exactly where they are.
|
|
173
|
+
- New nodes go next to the node they connect to.
|
|
174
|
+
- Removed nodes disappear.
|
|
175
|
+
- Groups grow to fit new members.
|
|
176
|
+
- Only new edges, and edges whose routes went stale, get rerouted.
|
|
177
|
+
- Their colours, label edits and notes survive.
|
|
178
|
+
|
|
179
|
+
The `merged into the existing layout:` line tells you what happened. Mention it to the user.
|
|
180
|
+
|
|
181
|
+
The `# linework-base:` line tells `build` your spec includes the latest hand edits. Without it, `build` won't delete shapes someone added by hand that your spec doesn't mention. It keeps them and prints a note. If you see that note, run `show` again and redo your edit from its output.
|
|
182
|
+
|
|
183
|
+
`--relayout` throws the hand-made layout away and lays everything out from scratch. **Only use it if the user asks,** because it undoes their layout work.
|
|
184
|
+
|
|
185
|
+
If someone moved shapes by hand and left edges crossing through boxes, `npx -y @itsthecsguy/linework tidy file.drawio.svg` reroutes just the broken edges and changes nothing else.
|
|
186
|
+
|
|
187
|
+
## Putting it in a doc
|
|
188
|
+
|
|
189
|
+
- Markdown (GitHub, GitLab, most renderers): ``
|
|
190
|
+
- HTML: `<img src="diagrams/checkout.drawio.svg" alt="Checkout architecture">`
|
|
191
|
+
- Tell the user they can edit it by hand: open the file in VS Code with the "Draw.io Integration" extension, in draw.io desktop, or at app.diagrams.net. It saves back into the same file, and your later edits will keep their layout.
|
|
192
|
+
- In a git repo, offer to run `npx -y @itsthecsguy/linework git-setup` once, so `git diff` on diagrams shows readable spec changes.
|
|
193
|
+
- Google Docs can't hold SVG. `npx -y @itsthecsguy/linework publish file.drawio.svg` copies it into the user's Google Drive folder, and draw.io's Google Docs add-on inserts it from there and refreshes it after changes. Setup and the update steps are in `references/google-docs.md`; walk the user through them the first time.
|
|
194
|
+
|
|
195
|
+
## Letting the user edit
|
|
196
|
+
|
|
197
|
+
If the user wants to adjust a diagram by hand, `npx -y @itsthecsguy/linework edit file.drawio.svg` opens it in draw.io in their browser, served from their machine. Saving there writes the file. When they say they're done, run `show` and carry on from its output; their changes are in it.
|
|
198
|
+
|
|
199
|
+
## Commands
|
|
200
|
+
|
|
201
|
+
| command | does |
|
|
202
|
+
|---|---|
|
|
203
|
+
| `build <spec\|-> -o out.drawio.svg [--png p.png] [--relayout]` | layout (or merge into an existing file), write, lint |
|
|
204
|
+
| `show <file> [--geometry]` | print the spec, stamped with `linework-base` |
|
|
205
|
+
| `tidy <file>` | reroute edges that pass through nodes; nothing else changes |
|
|
206
|
+
| `import <file.mmd\|doc.md> [--block N] [-o out.drawio.svg]` | convert Mermaid (flowchart, state, sequence, ER) |
|
|
207
|
+
| `icons <aws\|gcp\|k8s\|azure> [filter]` | list icon names |
|
|
208
|
+
| `edit <file>` | open the diagram in draw.io in the user's browser; saving writes the file |
|
|
209
|
+
| `publish <file...> [--to dir] [--pull]` | copy diagrams into Google Drive for the Docs add-on; `--pull` brings Drive edits back |
|
|
210
|
+
| `git-setup` | make `git diff` show diagram changes as spec changes |
|
|
211
|
+
| `render <file> -o out.png [--scale 2]` | preview image |
|
|
212
|
+
| `check <file>` | lint only; exit 1 on errors |
|
|
213
|
+
| `kinds [type]` | list node kinds |
|
|
214
|
+
| `schema` | JSON Schema of the spec |
|
|
@@ -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="886px" height="358px" viewBox="0 0 886 358" content="<mxfile host="aiviz" agent="aiviz"><diagram id="aiviz" name="Billing schema"><mxGraphModel grid="1" gridSize="8" guides="1" tooltips="1" connect="1" arrows="1" page="0" background="#FFFFFF" math="0" shadow="0"><root><object id="0" label="" aiviz_version="1" aiviz_type="er" aiviz_direction="auto" aiviz_title="Billing schema"><mxCell/></object><mxCell id="1" parent="0"/><object id="orgs" label="organizations" aiviz_kind="entity" aiviz_label="organizations" aiviz_auto="708,120,160,116"><mxCell style="shape=swimlane;childLayout=stackLayout;horizontal=1;startSize=32;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=0;marginBottom=0;rounded=1;absoluteArcSize=1;arcSize=12;swimlaneFillColor=#FFFFFF;fontStyle=1;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;" vertex="1" parent="1"><mxGeometry x="708" y="120" width="160" height="116" as="geometry"/></mxCell></object><object id="users" label="Users" aiviz_kind="entity" aiviz_label="Users" aiviz_auto="364,16,184,142"><mxCell style="shape=swimlane;childLayout=stackLayout;horizontal=1;startSize=32;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=0;marginBottom=0;rounded=1;absoluteArcSize=1;arcSize=12;swimlaneFillColor=#FFFFFF;fontStyle=1;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;" vertex="1" parent="1"><mxGeometry x="364" y="16" width="184" height="142" as="geometry"/></mxCell></object><object id="subscriptions" label="Subscriptions" aiviz_kind="entity" aiviz_label="Subscriptions" aiviz_auto="372,198,168,142"><mxCell style="shape=swimlane;childLayout=stackLayout;horizontal=1;startSize=32;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=0;marginBottom=0;rounded=1;absoluteArcSize=1;arcSize=12;swimlaneFillColor=#FFFFFF;fontStyle=1;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;" vertex="1" parent="1"><mxGeometry x="372" y="198" width="168" height="142" as="geometry"/></mxCell></object><object id="invoices" label="Invoices" aiviz_kind="entity" aiviz_label="Invoices" aiviz_auto="16,198,192,142"><mxCell style="shape=swimlane;childLayout=stackLayout;horizontal=1;startSize=32;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=0;marginBottom=0;rounded=1;absoluteArcSize=1;arcSize=12;swimlaneFillColor=#FFFFFF;fontStyle=1;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;" vertex="1" parent="1"><mxGeometry x="16" y="198" width="192" height="142" as="geometry"/></mxCell></object><object id="orgs__id" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;&lt;b&gt;id&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;uuid PK&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="id" aiviz_ftype="uuid" aiviz_flags="pk"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="orgs"><mxGeometry x="0" y="32" width="160" height="26" as="geometry"/></mxCell></object><object id="orgs__name" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;name&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;text&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="name" aiviz_ftype="text"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="orgs"><mxGeometry x="0" y="58" width="160" height="26" as="geometry"/></mxCell></object><object id="orgs__plan" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;plan&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;text&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="plan" aiviz_ftype="text"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="orgs"><mxGeometry x="0" y="84" width="160" height="26" as="geometry"/></mxCell></object><object id="users__id" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;&lt;b&gt;id&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;uuid PK&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="id" aiviz_ftype="uuid" aiviz_flags="pk"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="users"><mxGeometry x="0" y="32" width="184" height="26" as="geometry"/></mxCell></object><object id="users__org_id" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;org_id&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;uuid FK&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="org_id" aiviz_ftype="uuid" aiviz_flags="fk"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="users"><mxGeometry x="0" y="58" width="184" height="26" as="geometry"/></mxCell></object><object id="users__email" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;email&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;text unique&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="email" aiviz_ftype="text" aiviz_flags="unique"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="users"><mxGeometry x="0" y="84" width="184" height="26" as="geometry"/></mxCell></object><object id="users__created_at" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;created_at&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;timestamptz&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="created_at" aiviz_ftype="timestamptz"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="users"><mxGeometry x="0" y="110" width="184" height="26" as="geometry"/></mxCell></object><object id="subscriptions__id" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;&lt;b&gt;id&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;uuid PK&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="id" aiviz_ftype="uuid" aiviz_flags="pk"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="subscriptions"><mxGeometry x="0" y="32" width="168" height="26" as="geometry"/></mxCell></object><object id="subscriptions__org_id" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;org_id&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;uuid FK&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="org_id" aiviz_ftype="uuid" aiviz_flags="fk"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="subscriptions"><mxGeometry x="0" y="58" width="168" height="26" as="geometry"/></mxCell></object><object id="subscriptions__stripe_id" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;stripe_id&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;text unique&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="stripe_id" aiviz_ftype="text" aiviz_flags="unique"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="subscriptions"><mxGeometry x="0" y="84" width="168" height="26" as="geometry"/></mxCell></object><object id="subscriptions__status" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;status&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;text&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="status" aiviz_ftype="text"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="subscriptions"><mxGeometry x="0" y="110" width="168" height="26" as="geometry"/></mxCell></object><object id="invoices__id" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;&lt;b&gt;id&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;uuid PK&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="id" aiviz_ftype="uuid" aiviz_flags="pk"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="invoices"><mxGeometry x="0" y="32" width="192" height="26" as="geometry"/></mxCell></object><object id="invoices__subscription_id" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;subscription_id&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;uuid FK&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="subscription_id" aiviz_ftype="uuid" aiviz_flags="fk"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="invoices"><mxGeometry x="0" y="58" width="192" height="26" as="geometry"/></mxCell></object><object id="invoices__amount_cents" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;amount_cents&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;int&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="amount_cents" aiviz_ftype="int"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="invoices"><mxGeometry x="0" y="84" width="192" height="26" as="geometry"/></mxCell></object><object id="invoices__paid_at" label="&lt;table style=&quot;width:100%;height:100%;border-collapse:collapse&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:0 6px 0 12px&quot;&gt;paid_at&lt;/td&gt;&lt;td style=&quot;text-align:right;padding:0 12px 0 6px;color:#64748B&quot;&gt;timestamptz null&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;" aiviz_field="paid_at" aiviz_ftype="timestamptz" aiviz_flags="null"><mxCell style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=10;spacingRight=10;overflow=fill;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=12;fontColor=#0F172A;" vertex="1" parent="invoices"><mxGeometry x="0" y="110" width="192" height="26" as="geometry"/></mxCell></object><object id="e_users__orgs" label="belongs to" aiviz_edge="users-&gt;orgs" aiviz_auto="680,87 680,159"><mxCell style="edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;startArrow=ERzeroToMany;endArrow=ERmandOne;startFill=0;endFill=0;startSize=10;endSize=10;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.333;entryDx=0;entryDy=0;" edge="1" parent="1" source="users" target="orgs"><mxGeometry x="-0.309" relative="1" as="geometry"><Array as="points"><mxPoint x="680" y="87"/><mxPoint x="680" y="159"/></Array></mxGeometry></mxCell></object><object id="e_subscriptions__orgs" label="billed to" aiviz_edge="subscriptions-&gt;orgs" aiviz_auto="680,269 680,197"><mxCell style="edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;startArrow=ERzeroToMany;endArrow=ERmandOne;startFill=0;endFill=0;startSize=10;endSize=10;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.667;entryDx=0;entryDy=0;" edge="1" parent="1" source="subscriptions" target="orgs"><mxGeometry x="-0.266" relative="1" as="geometry"><Array as="points"><mxPoint x="680" y="269"/><mxPoint x="680" y="197"/></Array></mxGeometry></mxCell></object><object id="e_invoices__subscriptions" label="issued for" aiviz_edge="invoices-&gt;subscriptions" aiviz_auto=""><mxCell style="edgeStyle=orthogonalEdgeStyle;rounded=1;arcSize=12;html=1;strokeColor=#64748B;strokeWidth=1.5;startArrow=ERzeroToMany;endArrow=ERmandOne;startFill=0;endFill=0;startSize=10;endSize=10;fontFamily=-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;fontSize=11;fontColor=#475569;labelBackgroundColor=#FFFFFF;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="invoices" target="subscriptions"><mxGeometry x="-0.049" relative="1" as="geometry"/></mxCell></object></root></mxGraphModel></diagram></mxfile>"><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="orgs"><g><path d="M 868 152 L 868 126 Q 868 120 862 120 L 714 120 Q 708 120 708 126 L 708 152" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" 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));"/><path d="M 708 152 L 708 230 Q 708 236 714 236 L 862 236 Q 868 236 868 230 L 868 152" fill="#ffffff" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18)); stroke: light-dark(rgb(79, 70, 229), rgb(162, 154, 255));"/><path d="M 708 152 L 868 152" fill="none" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="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 center; width: 158px; height: 1px; padding-top: 136px; margin-left: 709px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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; font-weight: bold; white-space: normal; word-wrap: normal; ">organizations</div></div></div></foreignObject><text x="788" y="140" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" font-weight="bold" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">organizations</text></switch></g></g><g data-cell-id="orgs__id"><g><rect x="708" y="152" width="160" height="26" fill="none" stroke="none" pointer-events="all"/></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: 162px; height: 26px; padding-top: 152px; margin-left: 708px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 160px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px"><b>id</b></td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">uuid PK</td></tr></tbody></table></div></div></div></foreignObject><text x="708" y="169" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">iduuid PK</text></switch></g></g></g><g data-cell-id="orgs__name"><g><rect x="708" y="178" width="160" height="26" fill="none" stroke="none" pointer-events="all"/></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: 162px; height: 26px; padding-top: 178px; margin-left: 708px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 160px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">name</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">text</td></tr></tbody></table></div></div></div></foreignObject><text x="708" y="195" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">nametext</text></switch></g></g></g><g data-cell-id="orgs__plan"><g><rect x="708" y="204" width="160" height="26" fill="none" stroke="none" pointer-events="all"/></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: 162px; height: 26px; padding-top: 204px; margin-left: 708px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 160px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">plan</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">text</td></tr></tbody></table></div></div></div></foreignObject><text x="708" y="221" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">plantext</text></switch></g></g></g></g><g data-cell-id="users"><g><path d="M 548 48 L 548 22 Q 548 16 542 16 L 370 16 Q 364 16 364 22 L 364 48" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" 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));"/><path d="M 364 48 L 364 152 Q 364 158 370 158 L 542 158 Q 548 158 548 152 L 548 48" fill="#ffffff" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18)); stroke: light-dark(rgb(79, 70, 229), rgb(162, 154, 255));"/><path d="M 364 48 L 548 48" fill="none" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="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 center; width: 182px; height: 1px; padding-top: 32px; margin-left: 365px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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; font-weight: bold; white-space: normal; word-wrap: normal; ">Users</div></div></div></foreignObject><text x="456" y="36" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" font-weight="bold" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">Users</text></switch></g></g><g data-cell-id="users__id"><g><rect x="364" y="48" width="184" height="26" fill="none" stroke="none" pointer-events="all"/></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: 186px; height: 26px; padding-top: 48px; margin-left: 364px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 184px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px"><b>id</b></td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">uuid PK</td></tr></tbody></table></div></div></div></foreignObject><text x="364" y="65" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">iduuid PK</text></switch></g></g></g><g data-cell-id="users__org_id"><g><rect x="364" y="74" width="184" height="26" fill="none" stroke="none" pointer-events="all"/></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: 186px; height: 26px; padding-top: 74px; margin-left: 364px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 184px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">org_id</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">uuid FK</td></tr></tbody></table></div></div></div></foreignObject><text x="364" y="91" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">org_iduuid FK</text></switch></g></g></g><g data-cell-id="users__email"><g><rect x="364" y="100" width="184" height="26" fill="none" stroke="none" pointer-events="all"/></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: 186px; height: 26px; padding-top: 100px; margin-left: 364px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 184px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">email</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">text unique</td></tr></tbody></table></div></div></div></foreignObject><text x="364" y="117" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">emailtext unique</text></switch></g></g></g><g data-cell-id="users__created_at"><g><rect x="364" y="126" width="184" height="26" fill="none" stroke="none" pointer-events="all"/></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: 186px; height: 26px; padding-top: 126px; margin-left: 364px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 184px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">created_at</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">timestamptz</td></tr></tbody></table></div></div></div></foreignObject><text x="364" y="143" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">created_attimestamptz</text></switch></g></g></g></g><g data-cell-id="subscriptions"><g><path d="M 540 230 L 540 204 Q 540 198 534 198 L 378 198 Q 372 198 372 204 L 372 230" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" 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));"/><path d="M 372 230 L 372 334 Q 372 340 378 340 L 534 340 Q 540 340 540 334 L 540 230" fill="#ffffff" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18)); stroke: light-dark(rgb(79, 70, 229), rgb(162, 154, 255));"/><path d="M 372 230 L 540 230" fill="none" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="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 center; width: 166px; height: 1px; padding-top: 214px; margin-left: 373px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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; font-weight: bold; white-space: normal; word-wrap: normal; ">Subscriptions</div></div></div></foreignObject><text x="456" y="218" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" font-weight="bold" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">Subscriptions</text></switch></g></g><g data-cell-id="subscriptions__id"><g><rect x="372" y="230" width="168" height="26" fill="none" stroke="none" pointer-events="all"/></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: 170px; height: 26px; padding-top: 230px; margin-left: 372px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 168px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px"><b>id</b></td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">uuid PK</td></tr></tbody></table></div></div></div></foreignObject><text x="372" y="247" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">iduuid PK</text></switch></g></g></g><g data-cell-id="subscriptions__org_id"><g><rect x="372" y="256" width="168" height="26" fill="none" stroke="none" pointer-events="all"/></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: 170px; height: 26px; padding-top: 256px; margin-left: 372px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 168px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">org_id</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">uuid FK</td></tr></tbody></table></div></div></div></foreignObject><text x="372" y="273" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">org_iduuid FK</text></switch></g></g></g><g data-cell-id="subscriptions__stripe_id"><g><rect x="372" y="282" width="168" height="26" fill="none" stroke="none" pointer-events="all"/></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: 170px; height: 26px; padding-top: 282px; margin-left: 372px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 168px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">stripe_id</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">text unique</td></tr></tbody></table></div></div></div></foreignObject><text x="372" y="299" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">stripe_idtext unique</text></switch></g></g></g><g data-cell-id="subscriptions__status"><g><rect x="372" y="308" width="168" height="26" fill="none" stroke="none" pointer-events="all"/></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: 170px; height: 26px; padding-top: 308px; margin-left: 372px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 168px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">status</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">text</td></tr></tbody></table></div></div></div></foreignObject><text x="372" y="325" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">statustext</text></switch></g></g></g></g><g data-cell-id="invoices"><g><path d="M 208 230 L 208 204 Q 208 198 202 198 L 22 198 Q 16 198 16 204 L 16 230" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" 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));"/><path d="M 16 230 L 16 334 Q 16 340 22 340 L 202 340 Q 208 340 208 334 L 208 230" fill="#ffffff" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18)); stroke: light-dark(rgb(79, 70, 229), rgb(162, 154, 255));"/><path d="M 16 230 L 208 230" fill="none" stroke="#4f46e5" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="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 center; width: 190px; height: 1px; padding-top: 214px; margin-left: 17px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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; font-weight: bold; white-space: normal; word-wrap: normal; ">Invoices</div></div></div></foreignObject><text x="112" y="218" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" font-weight="bold" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">Invoices</text></switch></g></g><g data-cell-id="invoices__id"><g><rect x="16" y="230" width="192" height="26" fill="none" stroke="none" pointer-events="all"/></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: 194px; height: 26px; padding-top: 230px; margin-left: 16px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 192px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px"><b>id</b></td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">uuid PK</td></tr></tbody></table></div></div></div></foreignObject><text x="16" y="247" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">iduuid PK</text></switch></g></g></g><g data-cell-id="invoices__subscription_id"><g><rect x="16" y="256" width="192" height="26" fill="none" stroke="none" pointer-events="all"/></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: 194px; height: 26px; padding-top: 256px; margin-left: 16px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 192px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">subscription_id</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">uuid FK</td></tr></tbody></table></div></div></div></foreignObject><text x="16" y="273" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">subscription_iduuid FK</text></switch></g></g></g><g data-cell-id="invoices__amount_cents"><g><rect x="16" y="282" width="192" height="26" fill="none" stroke="none" pointer-events="all"/></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: 194px; height: 26px; padding-top: 282px; margin-left: 16px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 192px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">amount_cents</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">int</td></tr></tbody></table></div></div></div></foreignObject><text x="16" y="299" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">amount_centsint</text></switch></g></g></g><g data-cell-id="invoices__paid_at"><g><rect x="16" y="308" width="192" height="26" fill="none" stroke="none" pointer-events="all"/></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: 194px; height: 26px; padding-top: 308px; margin-left: 16px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; width: 192px; height: 26px; overflow: hidden; color: #0F172A; "><div style="display: inline-block; font-size: 12px; 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; width: 100%; height: 100%; white-space: normal; word-wrap: normal; "><table style="width:100%;height:100%;border-collapse:collapse"><tbody><tr><td style="padding:0 6px 0 12px">paid_at</td><td style="text-align: right; padding: 0px 12px 0px 6px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">timestamptz null</td></tr></tbody></table></div></div></div></foreignObject><text x="16" y="325" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="12px" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">paid_attimestamptz null</text></switch></g></g></g></g><g data-cell-id="e_users__orgs"><g><path d="M 572.25 87 L 674 87 Q 680 87 680 93 L 680 152.6 Q 680 158.6 686 158.61 L 708 158.63" 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));"/><ellipse cx="566.75" cy="87" rx="5" ry="5" fill="none" stroke="#64748b" stroke-width="1.5" pointer-events="all" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 548 93.25 L 560.5 87 L 548 80.75 M 560.5 87 L 548 87" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 701.74 164.87 L 701.76 152.37 M 695.49 164.87 L 695.51 152.37" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="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: 87px; margin-left: 628px;"><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; ">belongs to</div></div></div></foreignObject><text x="628" y="90" 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));">belongs to</text></switch></g></g></g><g data-cell-id="e_subscriptions__orgs"><g><path d="M 564.25 269 L 674 269 Q 680 269 680 263 L 680 203.4 Q 680 197.4 686 197.39 L 708 197.37" 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));"/><ellipse cx="558.75" cy="269" rx="5" ry="5" fill="none" stroke="#64748b" stroke-width="1.5" pointer-events="all" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 540 275.25 L 552.5 269 L 540 262.75 M 552.5 269 L 540 269" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 701.76 203.63 L 701.74 191.13 M 695.51 203.63 L 695.49 191.13" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="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: 269px; margin-left: 628px;"><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; ">billed to</div></div></div></foreignObject><text x="628" y="272" 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));">billed to</text></switch></g></g></g><g data-cell-id="e_invoices__subscriptions"><g><path d="M 232.25 269 L 372 269" 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));"/><ellipse cx="226.75" cy="269" rx="5" ry="5" fill="none" stroke="#64748b" stroke-width="1.5" pointer-events="all" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 208 275.25 L 220.5 269 L 208 262.75 M 220.5 269 L 208 269" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));"/><path d="M 365.75 275.25 L 365.75 262.75 M 359.5 275.25 L 359.5 262.75" fill="none" stroke="#64748b" stroke-width="1.5" stroke-miterlimit="10" pointer-events="all" style="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: 269px; margin-left: 286px;"><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; ">issued for</div></div></div></foreignObject><text x="286" y="272" 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));">issued for</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,31 @@
|
|
|
1
|
+
type: er
|
|
2
|
+
title: Billing schema
|
|
3
|
+
nodes:
|
|
4
|
+
orgs:
|
|
5
|
+
label: organizations
|
|
6
|
+
fields:
|
|
7
|
+
- id: uuid pk
|
|
8
|
+
- name: text
|
|
9
|
+
- plan: text
|
|
10
|
+
users:
|
|
11
|
+
fields:
|
|
12
|
+
- id: uuid pk
|
|
13
|
+
- org_id: uuid fk
|
|
14
|
+
- email: text unique
|
|
15
|
+
- created_at: timestamptz
|
|
16
|
+
subscriptions:
|
|
17
|
+
fields:
|
|
18
|
+
- id: uuid pk
|
|
19
|
+
- org_id: uuid fk
|
|
20
|
+
- stripe_id: text unique
|
|
21
|
+
- status: text
|
|
22
|
+
invoices:
|
|
23
|
+
fields:
|
|
24
|
+
- id: uuid pk
|
|
25
|
+
- subscription_id: uuid fk
|
|
26
|
+
- amount_cents: int
|
|
27
|
+
- paid_at: timestamptz null
|
|
28
|
+
edges:
|
|
29
|
+
- users }o--|| orgs: belongs to
|
|
30
|
+
- subscriptions }o--|| orgs: billed to
|
|
31
|
+
- invoices }o--|| subscriptions: issued for
|
|
@@ -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="656px" height="1187px" viewBox="0 0 656 1187" content="<mxfile host="aiviz" agent="aiviz"><diagram id="aiviz" name="Checkout"><mxGraphModel grid="1" gridSize="8" guides="1" tooltips="1" connect="1" arrows="1" page="0" background="#FFFFFF" math="0" shadow="0"><root><object id="0" label="" aiviz_version="1" aiviz_type="architecture" aiviz_direction="auto" aiviz_title="Checkout"><mxCell/></object><mxCell id="1" parent="0"/><object id="vpc" label="Production VPC" aiviz_type="group" aiviz_label="Production VPC" aiviz_auto="16,341,494,655"><mxCell style="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;" vertex="1" parent="1"><mxGeometry x="16" y="341" width="494" height="655" as="geometry"/></mxCell></object><object id="data" label="Data tier" aiviz_type="group" aiviz_label="Data tier" aiviz_auto="20,503,380,132"><mxCell style="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;" vertex="1" parent="vpc"><mxGeometry x="20" y="503" width="380" height="132" as="geometry"/></mxCell></object><object id="user" label="&lt;span style=&quot;font-weight:600&quot;&gt;Shopper&lt;/span&gt;" aiviz_kind="person" aiviz_label="Shopper" aiviz_auto="303,16,160,40"><mxCell style="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;" vertex="1" parent="1"><mxGeometry x="303" y="16" width="160" height="40" as="geometry"/></mxCell></object><object id="web" label="&lt;span style=&quot;font-weight:600&quot;&gt;Web app&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;font-size:11px;color:#64748B&quot;&gt;Next.js&lt;/span&gt;" aiviz_kind="client" aiviz_label="Web app" aiviz_tech="Next.js" aiviz_auto="303,168,160,56"><mxCell style="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=#F0F9FF;strokeColor=#0284C7;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="303" y="168" width="160" height="56" as="geometry"/></mxCell></object><object id="gw" label="&lt;span style=&quot;font-weight:600&quot;&gt;API gateway&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;font-size:11px;color:#64748B&quot;&gt;Envoy&lt;/span&gt;" aiviz_kind="service" aiviz_label="API gateway" aiviz_tech="Envoy" aiviz_auto="287,40,160,56"><mxCell style="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;" vertex="1" parent="vpc"><mxGeometry x="287" y="40" width="160" height="56" as="geometry"/></mxCell></object><object id="api" label="&lt;span style=&quot;font-weight:600&quot;&gt;Checkout API&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;font-size:11px;color:#64748B&quot;&gt;Go&lt;/span&gt;" aiviz_kind="service" aiviz_label="Checkout API" aiviz_tech="Go" aiviz_auto="287,152,160,56"><mxCell style="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;" vertex="1" parent="vpc"><mxGeometry x="287" y="152" width="160" height="56" as="geometry"/></mxCell></object><object id="worker" label="&lt;span style=&quot;font-weight:600&quot;&gt;Fulfillment worker&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;font-size:11px;color:#64748B&quot;&gt;Go&lt;/span&gt;" aiviz_kind="service" aiviz_label="Fulfillment worker" aiviz_tech="Go" aiviz_auto="303,386,160,56"><mxCell style="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;" vertex="1" parent="vpc"><mxGeometry x="303" y="386" width="160" height="56" as="geometry"/></mxCell></object><object id="queue" label="&lt;span style=&quot;font-weight:600&quot;&gt;order-events&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;font-size:11px;color:#64748B&quot;&gt;Kafka&lt;/span&gt;" aiviz_kind="queue" aiviz_label="order-events" aiviz_tech="Kafka" aiviz_auto="303,274,160,56"><mxCell style="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;" vertex="1" parent="vpc"><mxGeometry x="303" y="274" width="160" height="56" as="geometry"/></mxCell></object><object id="db" label="&lt;span style=&quot;font-weight:600&quot;&gt;Orders&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;font-size:11px;color:#64748B&quot;&gt;Postgres&lt;/span&gt;" aiviz_kind="database" aiviz_label="Orders" aiviz_tech="Postgres" aiviz_auto="200,40,160,72"><mxCell style="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;" vertex="1" parent="data"><mxGeometry x="200" y="40" width="160" height="72" as="geometry"/></mxCell></object><object id="cache" label="&lt;span style=&quot;font-weight:600&quot;&gt;Session cache&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;font-size:11px;color:#64748B&quot;&gt;Redis&lt;/span&gt;" aiviz_kind="cache" aiviz_label="Session cache" aiviz_tech="Redis" aiviz_auto="20,40,160,56"><mxCell style="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=#ECFDF5;strokeColor=#059669;strokeWidth=1.5;" vertex="1" parent="data"><mxGeometry x="20" y="40" width="160" height="56" as="geometry"/></mxCell></object><object id="stripe" label="&lt;span style=&quot;font-weight:600&quot;&gt;Stripe&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;font-size:11px;color:#64748B&quot;&gt;Payments API&lt;/span&gt;" aiviz_kind="external" aiviz_label="Stripe" aiviz_tech="Payments API" aiviz_auto="478,1113,160,56"><mxCell style="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=#F8FAFC;strokeColor=#94A3B8;strokeWidth=1.5;dashed=1;dashPattern=6 4;" vertex="1" parent="1"><mxGeometry x="478" y="1113" width="160" height="56" as="geometry"/></mxCell></object><object id="email" label="&lt;span style=&quot;font-weight:600&quot;&gt;SendGrid&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;font-size:11px;color:#64748B&quot;&gt;Email&lt;/span&gt;" aiviz_kind="external" aiviz_label="SendGrid" aiviz_tech="Email" aiviz_auto="278,1113,160,56"><mxCell style="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=#F8FAFC;strokeColor=#94A3B8;strokeWidth=1.5;dashed=1;dashPattern=6 4;" vertex="1" parent="1"><mxGeometry x="278" y="1113" width="160" height="56" as="geometry"/></mxCell></object><object id="e_user__web" label="browses" aiviz_edge="user-&gt;web" aiviz_auto=""><mxCell style="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;" edge="1" parent="1" source="user" target="web"><mxGeometry relative="1" as="geometry"/></mxCell></object><object id="e_web__gw" label="HTTPS" aiviz_edge="web-&gt;gw" aiviz_auto=""><mxCell style="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;" edge="1" parent="1" source="web" target="gw"><mxGeometry x="-0.287" relative="1" as="geometry"/></mxCell></object><object id="e_gw__api" label="gRPC" aiviz_edge="gw-&gt;api" aiviz_auto=""><mxCell style="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;" edge="1" parent="1" source="gw" target="api"><mxGeometry relative="1" as="geometry"/></mxCell></object><object id="e_api__cache" label="read session" aiviz_edge="api-&gt;cache" aiviz_auto="335,559 136,559"><mxCell style="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.2;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="api" target="cache"><mxGeometry x="0.308" relative="1" as="geometry"><Array as="points"><mxPoint x="335" y="559"/><mxPoint x="136" y="559"/></Array></mxGeometry></mxCell></object><object id="e_api__db" label="SQL" aiviz_edge="api-&gt;db" aiviz_auto="367,569 249,569 249,829 289,829"><mxCell style="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.4;exitY=1;exitDx=0;exitDy=0;entryX=0.333;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="api" target="db"><mxGeometry x="0.087" relative="1" as="geometry"><Array as="points"><mxPoint x="367" y="569"/><mxPoint x="249" y="569"/><mxPoint x="249" y="829"/><mxPoint x="289" y="829"/></Array></mxGeometry></mxCell></object><object id="e_api__stripe" label="charge" aiviz_edge="api-&gt;stripe" aiviz_auto="431,559 489,559 489,1021 558,1021"><mxCell style="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.8;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="api" target="stripe"><mxGeometry x="0.838" relative="1" as="geometry"><Array as="points"><mxPoint x="431" y="559"/><mxPoint x="489" y="559"/><mxPoint x="489" y="1021"/><mxPoint x="558" y="1021"/></Array></mxGeometry></mxCell></object><object id="e_api__queue" label="OrderPlaced" aiviz_edge="api-&gt;queue" aiviz_auto=""><mxCell style="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.6;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="api" target="queue"><mxGeometry x="0.152" relative="1" as="geometry"/></mxCell></object><object id="e_queue__worker" label="consume" aiviz_edge="queue-&gt;worker" aiviz_auto=""><mxCell style="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.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="queue" target="worker"><mxGeometry relative="1" as="geometry"/></mxCell></object><object id="e_worker__db" label="update status" aiviz_edge="worker-&gt;db" aiviz_auto="373,793 343,793"><mxCell style="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.667;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="worker" target="db"><mxGeometry x="-0.115" relative="1" as="geometry"><Array as="points"><mxPoint x="373" y="793"/><mxPoint x="343" y="793"/></Array></mxGeometry></mxCell></object><object id="e_worker__email" label="receipt" aiviz_edge="worker-&gt;email" aiviz_auto="426,1021 358,1021"><mxCell style="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.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="worker" target="email"><mxGeometry x="0.719" relative="1" as="geometry"><Array as="points"><mxPoint x="426" y="1021"/><mxPoint x="358" y="1021"/></Array></mxGeometry></mxCell></object></root></mxGraphModel></diagram></mxfile>"><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="vpc"><g transform="translate(0.5,0.5)"><rect x="16" y="341" width="494" height="655" 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: 478px; height: 1px; padding-top: 354px; 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; ">Production VPC</div></div></div></foreignObject><text x="32" y="365" 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));">Production VPC</text></switch></g></g><g data-cell-id="data"><g transform="translate(0.5,0.5)"><rect x="36" y="844" width="380" height="132" 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: 364px; height: 1px; padding-top: 857px; margin-left: 52px;"><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; ">Data tier</div></div></div></foreignObject><text x="52" y="868" 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));">Data tier</text></switch></g></g><g data-cell-id="db"><g><path d="M 236 892 C 236 887.58 271.82 884 316 884 C 337.22 884 357.57 884.84 372.57 886.34 C 387.57 887.84 396 889.88 396 892 L 396 948 C 396 952.42 360.18 956 316 956 C 271.82 956 236 952.42 236 948 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 396 892 C 396 896.42 360.18 900 316 900 C 271.82 900 236 896.42 236 892" 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 center; width: 158px; height: 1px; padding-top: 927px; margin-left: 237px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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">Orders</span><br /><span style="font-size: 11px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">Postgres</span></div></div></div></foreignObject><text x="316" y="923" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));"><tspan x="316" y="923">Orders</tspan><tspan x="316" y="939">Postgres</tspan></text></switch></g></g></g><g data-cell-id="cache"><g><rect x="56" y="884" width="160" height="56" rx="8" ry="8" fill="#ecfdf5" stroke="#059669" stroke-width="1.5" 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));"/></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: 158px; height: 1px; padding-top: 912px; margin-left: 57px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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">Session cache</span><br /><span style="font-size: 11px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">Redis</span></div></div></div></foreignObject><text x="136" y="908" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));"><tspan x="136" y="908">Session cache</tspan><tspan x="136" y="924">Redis</tspan></text></switch></g></g></g></g><g data-cell-id="gw"><g><rect x="303" y="381" width="160" height="56" 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 center; width: 158px; height: 1px; padding-top: 409px; margin-left: 304px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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">API gateway</span><br /><span style="font-size: 11px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">Envoy</span></div></div></div></foreignObject><text x="383" y="405" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));"><tspan x="383" y="405">API gateway</tspan><tspan x="383" y="421">Envoy</tspan></text></switch></g></g></g><g data-cell-id="api"><g><rect x="303" y="493" width="160" height="56" 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 center; width: 158px; height: 1px; padding-top: 521px; margin-left: 304px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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">Checkout API</span><br /><span style="font-size: 11px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">Go</span></div></div></div></foreignObject><text x="383" y="517" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));"><tspan x="383" y="517">Checkout API</tspan><tspan x="383" y="533">Go</tspan></text></switch></g></g></g><g data-cell-id="worker"><g><rect x="319" y="727" width="160" height="56" 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 center; width: 158px; height: 1px; padding-top: 755px; margin-left: 320px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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">Fulfillment worker</span><br /><span style="font-size: 11px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">Go</span></div></div></div></foreignObject><text x="399" y="751" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));"><tspan x="399" y="751">Fulfillment worker</tspan><tspan x="399" y="767">Go</tspan></text></switch></g></g></g><g data-cell-id="queue"><g><rect x="319" y="615" width="160" height="56" rx="28" ry="28" 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 center; width: 158px; height: 1px; padding-top: 643px; margin-left: 320px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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">order-events</span><br /><span style="font-size: 11px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">Kafka</span></div></div></div></foreignObject><text x="399" y="639" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));"><tspan x="399" y="639">order-events</tspan><tspan x="399" y="655">Kafka</tspan></text></switch></g></g></g></g><g data-cell-id="user"><g><rect x="303" y="16" width="160" 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 center; width: 158px; height: 1px; padding-top: 36px; margin-left: 304px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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">Shopper</span></div></div></div></foreignObject><text x="383" y="40" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));">Shopper</text></switch></g></g></g><g data-cell-id="web"><g><rect x="303" y="168" width="160" height="56" rx="8" ry="8" fill="#f0f9ff" stroke="#0284c7" stroke-width="1.5" pointer-events="all" style="fill: light-dark(rgb(240, 249, 255), rgb(18, 26, 31)); stroke: light-dark(rgb(2, 132, 199), rgb(52, 163, 221));"/></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: 158px; height: 1px; padding-top: 196px; margin-left: 304px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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">Web app</span><br /><span style="font-size: 11px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">Next.js</span></div></div></div></foreignObject><text x="383" y="192" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));"><tspan x="383" y="192">Web app</tspan><tspan x="383" y="208">Next.js</tspan></text></switch></g></g></g><g data-cell-id="stripe"><g><rect x="478" y="1113" width="160" height="56" rx="8" ry="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.5" stroke-dasharray="9 6" pointer-events="all" style="fill: light-dark(rgb(248, 250, 252), rgb(21, 23, 25)); stroke: light-dark(rgb(148, 163, 184), rgb(87, 100, 118));"/></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: 158px; height: 1px; padding-top: 1141px; margin-left: 479px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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">Stripe</span><br /><span style="font-size: 11px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">Payments API</span></div></div></div></foreignObject><text x="558" y="1137" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));"><tspan x="558" y="1137">Stripe</tspan><tspan x="558" y="1153">Payments API</tspan></text></switch></g></g></g><g data-cell-id="email"><g><rect x="278" y="1113" width="160" height="56" rx="8" ry="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.5" stroke-dasharray="9 6" pointer-events="all" style="fill: light-dark(rgb(248, 250, 252), rgb(21, 23, 25)); stroke: light-dark(rgb(148, 163, 184), rgb(87, 100, 118));"/></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: 158px; height: 1px; padding-top: 1141px; margin-left: 279px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; 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">SendGrid</span><br /><span style="font-size: 11px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));">Email</span></div></div></div></foreignObject><text x="358" y="1137" fill="#0F172A" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif" font-size="13px" text-anchor="middle" style="fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));"><tspan x="358" y="1137">SendGrid</tspan><tspan x="358" y="1153">Email</tspan></text></switch></g></g></g><g data-cell-id="e_user__web"><g><path d="M 383 56 L 383 157.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 383 166.32 L 380.17 157.82 L 385.83 157.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: 112px; margin-left: 383px;"><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; ">browses</div></div></div></foreignObject><text x="383" 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));">browses</text></switch></g></g></g><g data-cell-id="e_web__gw"><g><path d="M 383 224 L 383 370.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 383 379.32 L 380.17 370.82 L 385.83 370.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: 280px; margin-left: 383px;"><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; ">HTTPS</div></div></div></foreignObject><text x="383" y="283" 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));">HTTPS</text></switch></g></g></g><g data-cell-id="e_gw__api"><g><path d="M 383 437 L 383 482.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 383 491.32 L 380.17 482.82 L 385.83 482.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: 465px; margin-left: 383px;"><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; ">gRPC</div></div></div></foreignObject><text x="383" y="468" 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));">gRPC</text></switch></g></g></g><g data-cell-id="e_api__cache"><g><path d="M 335 549 L 335 554 Q 335 559 329 559 L 142 559 Q 136 559 136 565 L 136 873.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 136 882.32 L 133.17 873.82 L 138.83 873.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: 699px; margin-left: 136px;"><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; ">read session</div></div></div></foreignObject><text x="136" y="702" 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));">read session</text></switch></g></g></g><g data-cell-id="e_api__db"><g><path d="M 367 549 L 367 563 Q 367 569 361 569 L 255 569 Q 249 569 249 575 L 249 823 Q 249 829 255 829 L 283.3 829 Q 289.3 829 289.3 835 L 289.28 873.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 289.28 882.32 L 286.45 873.82 L 292.12 873.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: 699px; margin-left: 249px;"><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; ">SQL</div></div></div></foreignObject><text x="249" y="702" 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));">SQL</text></switch></g></g></g><g data-cell-id="e_api__stripe"><g><path d="M 431 549 L 431 554 Q 431 559 437 559 L 483 559 Q 489 559 489 565 L 489 1015 Q 489 1021 495 1021 L 552 1021 Q 558 1021 558 1027 L 558 1102.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 558 1111.32 L 555.17 1102.82 L 560.83 1102.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: 1057px; margin-left: 558px;"><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; ">charge</div></div></div></foreignObject><text x="558" y="1060" 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));">charge</text></switch></g></g></g><g data-cell-id="e_api__queue"><g><path d="M 399 549 L 399 604.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 399 613.32 L 396.17 604.82 L 401.83 604.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: 587px; margin-left: 399px;"><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; ">OrderPlaced</div></div></div></foreignObject><text x="399" y="590" 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));">OrderPlaced</text></switch></g></g></g><g data-cell-id="e_queue__worker"><g><path d="M 399 671 L 399 716.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 399 725.32 L 396.17 716.82 L 401.83 716.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: 699px; margin-left: 399px;"><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; ">consume</div></div></div></foreignObject><text x="399" y="702" 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));">consume</text></switch></g></g></g><g data-cell-id="e_worker__db"><g><path d="M 372.28 783 L 372.29 788 Q 372.3 793 366.3 793 L 348.7 793 Q 342.7 793 342.7 799 L 342.72 873.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 342.72 882.32 L 339.88 873.82 L 345.55 873.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: 811px; margin-left: 343px;"><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; ">update status</div></div></div></foreignObject><text x="343" y="815" 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));">update status</text></switch></g></g></g><g data-cell-id="e_worker__email"><g><path d="M 425.72 783 L 425.7 1015 Q 425.7 1021 419.7 1021 L 364 1021 Q 358 1021 358 1027 L 358 1102.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 358 1111.32 L 355.17 1102.82 L 360.83 1102.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: 1057px; margin-left: 358px;"><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; ">receipt</div></div></div></foreignObject><text x="358" y="1061" 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));">receipt</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>
|