chartlet 0.20.0

Compile structured data into deterministic, accessible static charts
Documentation
1
<div class="chartlet-wrapper chartlet-responsive chartlet-bp-640"><style>.chartlet-wrapper.chartlet-responsive{display:block;width:100%;container-type:inline-size}.chartlet-variant-mobile{display:none}@container (max-width:639px){.chartlet-bp-640 .chartlet-variant-desktop{display:none}.chartlet-bp-640 .chartlet-variant-mobile{display:block}}</style><style>.chartlet-stage{position:relative;display:inline-block;max-width:100%;vertical-align:top}.chartlet-stage>svg{display:block}.chartlet-hotspot{position:absolute;border-radius:8px;cursor:pointer}.chartlet-focus{margin:0 0 12px 0;font-size:13px}.chartlet-focus summary{cursor:pointer;min-height:24px}.chartlet-focus fieldset{border:none;padding:0;margin:4px 0 0 0}.chartlet-focus label{display:inline-flex;align-items:center;min-height:44px;margin-right:14px;cursor:pointer;white-space:nowrap}.chartlet-focus input{margin-right:4px}.chartlet-focus input:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.chartlet-wrapper:has(.chartlet-focus-node:checked) #chartlet-993d7890224c2061 .chartlet-f{opacity:.18}#chartlet-993d7890224c2061-hs-0{left:39.685%;top:1.091%;width:10.678%;height:4.909%}#chartlet-993d7890224c2061-hs-1{left:40.691%;top:11.851%;width:8.667%;height:4.364%}#chartlet-993d7890224c2061-hs-2{left:40.151%;top:26.264%;width:9.746%;height:6.182%}#chartlet-993d7890224c2061-hs-3{left:40.691%;top:40.94%;width:8.667%;height:4.545%}#chartlet-993d7890224c2061-hs-4{left:29.691%;top:53.687%;width:8.667%;height:6.182%}#chartlet-993d7890224c2061-hs-5{left:40.691%;top:54.505%;width:8.667%;height:4.545%}#chartlet-993d7890224c2061-hs-6{left:38.111%;top:77.93%;width:13.825%;height:5.455%}#chartlet-993d7890224c2061-hs-7{left:54.27%;top:77.93%;width:8.667%;height:5.455%}#chartlet-993d7890224c2061-hs-8{left:36.397%;top:93.636%;width:10%;height:4.909%}#chartlet-993d7890224c2061-hs-9{left:51.691%;top:11.76%;width:10.071%;height:4.545%}#chartlet-993d7890224c2061-hs-10{left:63.643%;top:94.455%;width:8.667%;height:3.273%}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-0:checked) #chartlet-993d7890224c2061 .chartlet-f-0{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-0:checked) #chartlet-993d7890224c2061 .chartlet-n-0 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-0:checked) #chartlet-993d7890224c2061 .chartlet-n-0 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-1:checked) #chartlet-993d7890224c2061 .chartlet-f-1{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-1:checked) #chartlet-993d7890224c2061 .chartlet-n-1 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-1:checked) #chartlet-993d7890224c2061 .chartlet-n-1 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-2:checked) #chartlet-993d7890224c2061 .chartlet-f-2{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-2:checked) #chartlet-993d7890224c2061 .chartlet-n-2 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-2:checked) #chartlet-993d7890224c2061 .chartlet-n-2 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-3:checked) #chartlet-993d7890224c2061 .chartlet-f-3{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-3:checked) #chartlet-993d7890224c2061 .chartlet-n-3 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-3:checked) #chartlet-993d7890224c2061 .chartlet-n-3 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-4:checked) #chartlet-993d7890224c2061 .chartlet-f-4{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-4:checked) #chartlet-993d7890224c2061 .chartlet-n-4 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-4:checked) #chartlet-993d7890224c2061 .chartlet-n-4 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-5:checked) #chartlet-993d7890224c2061 .chartlet-f-5{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-5:checked) #chartlet-993d7890224c2061 .chartlet-n-5 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-5:checked) #chartlet-993d7890224c2061 .chartlet-n-5 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-6:checked) #chartlet-993d7890224c2061 .chartlet-f-6{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-6:checked) #chartlet-993d7890224c2061 .chartlet-n-6 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-6:checked) #chartlet-993d7890224c2061 .chartlet-n-6 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-7:checked) #chartlet-993d7890224c2061 .chartlet-f-7{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-7:checked) #chartlet-993d7890224c2061 .chartlet-n-7 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-7:checked) #chartlet-993d7890224c2061 .chartlet-n-7 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-8:checked) #chartlet-993d7890224c2061 .chartlet-f-8{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-8:checked) #chartlet-993d7890224c2061 .chartlet-n-8 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-8:checked) #chartlet-993d7890224c2061 .chartlet-n-8 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-9:checked) #chartlet-993d7890224c2061 .chartlet-f-9{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-9:checked) #chartlet-993d7890224c2061 .chartlet-n-9 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-9:checked) #chartlet-993d7890224c2061 .chartlet-n-9 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-10:checked) #chartlet-993d7890224c2061 .chartlet-f-10{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-10:checked) #chartlet-993d7890224c2061 .chartlet-n-10 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-10:checked) #chartlet-993d7890224c2061 .chartlet-n-10 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(.chartlet-focus-node:checked) #chartlet-993d7890224c2061-m .chartlet-f{opacity:.18}#chartlet-993d7890224c2061-m-hs-0{left:35.485%;top:1.017%;width:17.304%;height:5.932%}#chartlet-993d7890224c2061-m-hs-1{left:35.429%;top:13.355%;width:17.416%;height:4.068%}#chartlet-993d7890224c2061-m-hs-2{left:31.535%;top:27.941%;width:25.205%;height:5.763%}#chartlet-993d7890224c2061-m-hs-3{left:34.224%;top:42.025%;width:19.825%;height:4.237%}#chartlet-993d7890224c2061-m-hs-4{left:8%;top:54.297%;width:22.384%;height:5.763%}#chartlet-993d7890224c2061-m-hs-5{left:33.832%;top:55.059%;width:20.61%;height:4.237%}#chartlet-993d7890224c2061-m-hs-6{left:32.992%;top:77.754%;width:22.291%;height:6.271%}#chartlet-993d7890224c2061-m-hs-7{left:58.731%;top:78.347%;width:18.591%;height:5.085%}#chartlet-993d7890224c2061-m-hs-8{left:27.672%;top:94.068%;width:22.039%;height:4.576%}#chartlet-993d7890224c2061-m-hs-9{left:56.293%;top:12.592%;width:22.052%;height:5.593%}#chartlet-993d7890224c2061-m-hs-10{left:75.89%;top:94.831%;width:21.282%;height:3.051%}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-0:checked) #chartlet-993d7890224c2061-m .chartlet-f-0{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-0:checked) #chartlet-993d7890224c2061-m .chartlet-n-0 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-0:checked) #chartlet-993d7890224c2061-m .chartlet-n-0 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-1:checked) #chartlet-993d7890224c2061-m .chartlet-f-1{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-1:checked) #chartlet-993d7890224c2061-m .chartlet-n-1 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-1:checked) #chartlet-993d7890224c2061-m .chartlet-n-1 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-2:checked) #chartlet-993d7890224c2061-m .chartlet-f-2{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-2:checked) #chartlet-993d7890224c2061-m .chartlet-n-2 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-2:checked) #chartlet-993d7890224c2061-m .chartlet-n-2 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-3:checked) #chartlet-993d7890224c2061-m .chartlet-f-3{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-3:checked) #chartlet-993d7890224c2061-m .chartlet-n-3 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-3:checked) #chartlet-993d7890224c2061-m .chartlet-n-3 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-4:checked) #chartlet-993d7890224c2061-m .chartlet-f-4{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-4:checked) #chartlet-993d7890224c2061-m .chartlet-n-4 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-4:checked) #chartlet-993d7890224c2061-m .chartlet-n-4 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-5:checked) #chartlet-993d7890224c2061-m .chartlet-f-5{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-5:checked) #chartlet-993d7890224c2061-m .chartlet-n-5 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-5:checked) #chartlet-993d7890224c2061-m .chartlet-n-5 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-6:checked) #chartlet-993d7890224c2061-m .chartlet-f-6{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-6:checked) #chartlet-993d7890224c2061-m .chartlet-n-6 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-6:checked) #chartlet-993d7890224c2061-m .chartlet-n-6 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-7:checked) #chartlet-993d7890224c2061-m .chartlet-f-7{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-7:checked) #chartlet-993d7890224c2061-m .chartlet-n-7 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-7:checked) #chartlet-993d7890224c2061-m .chartlet-n-7 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-8:checked) #chartlet-993d7890224c2061-m .chartlet-f-8{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-8:checked) #chartlet-993d7890224c2061-m .chartlet-n-8 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-8:checked) #chartlet-993d7890224c2061-m .chartlet-n-8 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-9:checked) #chartlet-993d7890224c2061-m .chartlet-f-9{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-9:checked) #chartlet-993d7890224c2061-m .chartlet-n-9 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-9:checked) #chartlet-993d7890224c2061-m .chartlet-n-9 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-10:checked) #chartlet-993d7890224c2061-m .chartlet-f-10{opacity:1}.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-10:checked) #chartlet-993d7890224c2061-m .chartlet-n-10 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-993d7890224c2061-focus-10:checked) #chartlet-993d7890224c2061-m .chartlet-n-10 .chartlet-seq-box{stroke-width:3}</style><details class="chartlet-focus"><summary>Focus</summary><fieldset><label><input type="radio" name="chartlet-993d7890224c2061-focus" checked> Show all</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-0"> Teacher, parent</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-1"> Browser</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-2"> Reverse proxy</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-3"> Web / BFF</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-4"> Sign-in</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-5"> Domain API</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-6"> Domain data</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-7"> Audit log</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-8"> Backup</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-9"> School records</label><label><input type="radio" name="chartlet-993d7890224c2061-focus" class="chartlet-focus-node" id="chartlet-993d7890224c2061-focus-10"> SIEM / SOC</label></fieldset></details><figure class="chartlet-figure" data-viz="chart"><figcaption>Multi-tenant line-of-business application</figcaption><div class="chartlet-variant-desktop"><div class="chartlet-stage"><svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1100" viewBox="0 0 1200 1100" id="chartlet-993d7890224c2061" role="img" aria-labelledby="chartlet-993d7890224c2061-title chartlet-993d7890224c2061-description" class="chartlet-root"><title id="chartlet-993d7890224c2061-title">Multi-tenant line-of-business application</title><desc id="chartlet-993d7890224c2061-description">Architecture diagram with 11 components and 10 connections in 3 boundaries. Data center: Reverse proxy, Application network. Application network (in Data center): Web / BFF, Sign-in, Domain API, Data zone. Data zone (in Application network): Domain data, Audit log. Main path: Teacher, parent → Browser → Reverse proxy → Web / BFF → Domain API → Domain data. Most connected: Domain API (5 connections). Nothing leads into Teacher, parent and School records. Teacher, parent (person): connects to Browser (uses). Browser (frontend): connects to Reverse proxy (calls, via HTTPS). School records (external system): connects to Domain API (master data, via REST/JSON). Reverse proxy (security): connects to Web / BFF (forwards). Web / BFF (service): connects to Sign-in (signs in, via OIDC) and Domain API (queries, via user context). Sign-in (security): no outgoing connection. Domain API (service): connects to Domain data (reads, writes, via SQL/TLS), Audit log (logs) and SIEM / SOC (events, via Syslog). Domain data (database): connects to Backup (backs up). Audit log (database): no outgoing connection. Backup (storage): no outgoing connection. SIEM / SOC (external system): no outgoing connection.</desc><style>.chartlet-root{--chartlet-text:#172033;--chartlet-muted:#344054;--chartlet-grid:#d9dee8;--chartlet-zero:#667085;--chartlet-accent:#2563eb;--chartlet-background:#fff;--chartlet-color-1:#2563eb;--chartlet-color-2:#c2410c;--chartlet-color-3:#475569;--chartlet-color-4:#111827;max-width:100%;height:auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif;color:var(--chartlet-text)}#chartlet-993d7890224c2061 .chartlet-title{font-size:22px;font-weight:650;fill:var(--chartlet-text)}#chartlet-993d7890224c2061 .chartlet-label,#chartlet-993d7890224c2061 .chartlet-tick,#chartlet-993d7890224c2061 .chartlet-value,#chartlet-993d7890224c2061 .chartlet-value-inverse,#chartlet-993d7890224c2061 .chartlet-axis-title{font-size:12px;fill:var(--chartlet-muted)}#chartlet-993d7890224c2061 .chartlet-value,#chartlet-993d7890224c2061 .chartlet-value-inverse{font-weight:600}#chartlet-993d7890224c2061 .chartlet-value{fill:var(--chartlet-text)}#chartlet-993d7890224c2061 .chartlet-value-inverse{fill:var(--chartlet-background)}#chartlet-993d7890224c2061 .chartlet-axis-title{font-weight:600}#chartlet-993d7890224c2061 .chartlet-grid{stroke:var(--chartlet-grid);stroke-width:1}#chartlet-993d7890224c2061 .chartlet-zero{stroke:var(--chartlet-zero);stroke-width:1.5}#chartlet-993d7890224c2061 .chartlet-bar,#chartlet-993d7890224c2061 .chartlet-point{fill:var(--chartlet-accent)}#chartlet-993d7890224c2061 .chartlet-line{fill:none;stroke:var(--chartlet-accent);stroke-width:3;stroke-linecap:round;stroke-linejoin:round}#chartlet-993d7890224c2061 .chartlet-background{fill:var(--chartlet-background)}.chartlet-root{--chartlet-node:#eef3fd;--chartlet-lane:#f7f9fc;--chartlet-lane-head:#eef1f6;--chartlet-shadow:rgba(16,24,40,.09);--chartlet-role-blue:#2563eb;--chartlet-role-blue-fill:#eef3fd;--chartlet-role-green:#15803d;--chartlet-role-green-fill:#ecfdf3;--chartlet-role-amber:#b45309;--chartlet-role-amber-fill:#fff7e8;--chartlet-role-teal:#0f766e;--chartlet-role-teal-fill:#e9faf7;--chartlet-role-violet:#6d28d9;--chartlet-role-violet-fill:#f3efff;--chartlet-role-gray:#667085;--chartlet-role-gray-fill:#f7f8fa;--chartlet-role-red:#b42318;--chartlet-role-red-fill:#fef3f2}.chartlet-root.chartlet-theme-dark{--chartlet-node:#1a2436;--chartlet-lane:#121925;--chartlet-lane-head:#18212f;--chartlet-shadow:rgba(0,0,0,.45);--chartlet-role-blue:#7ea6ff;--chartlet-role-blue-fill:#1a2436;--chartlet-role-green:#4ade80;--chartlet-role-green-fill:#132a1d;--chartlet-role-amber:#fbbf24;--chartlet-role-amber-fill:#2b2210;--chartlet-role-teal:#2dd4bf;--chartlet-role-teal-fill:#0f2a27;--chartlet-role-violet:#b69cff;--chartlet-role-violet-fill:#231c38;--chartlet-role-gray:#9aa7bd;--chartlet-role-gray-fill:#161d29;--chartlet-role-red:#f97066;--chartlet-role-red-fill:#2d1616}#chartlet-993d7890224c2061 .chartlet-role-blue{fill:var(--chartlet-role-blue-fill);stroke:var(--chartlet-role-blue)}#chartlet-993d7890224c2061 .chartlet-role-green{fill:var(--chartlet-role-green-fill);stroke:var(--chartlet-role-green)}#chartlet-993d7890224c2061 .chartlet-role-amber{fill:var(--chartlet-role-amber-fill);stroke:var(--chartlet-role-amber)}#chartlet-993d7890224c2061 .chartlet-role-teal{fill:var(--chartlet-role-teal-fill);stroke:var(--chartlet-role-teal)}#chartlet-993d7890224c2061 .chartlet-role-violet{fill:var(--chartlet-role-violet-fill);stroke:var(--chartlet-role-violet)}#chartlet-993d7890224c2061 .chartlet-role-gray{fill:var(--chartlet-role-gray-fill);stroke:var(--chartlet-role-gray)}#chartlet-993d7890224c2061 .chartlet-role-red{fill:var(--chartlet-role-red-fill);stroke:var(--chartlet-role-red)}#chartlet-993d7890224c2061 .chartlet-diagram-rim{fill:none;stroke:var(--chartlet-role-teal);stroke-width:1.5}#chartlet-993d7890224c2061 .chartlet-diagram-shadow{fill:var(--chartlet-shadow);stroke:none;rx:7px}#chartlet-993d7890224c2061 .chartlet-diagram-chip{fill:var(--chartlet-background);stroke:var(--chartlet-grid);stroke-width:1;rx:4px}#chartlet-993d7890224c2061 .chartlet-diagram-chip-text{font-size:12px;fill:var(--chartlet-text)}#chartlet-993d7890224c2061 .chartlet-diagram-badge{fill:var(--chartlet-accent);stroke:var(--chartlet-background);stroke-width:2}#chartlet-993d7890224c2061 .chartlet-diagram-badge-text{font-size:10px;font-weight:700;fill:var(--chartlet-background)}#chartlet-993d7890224c2061 .chartlet-flow-node{stroke-width:1.5;stroke-linejoin:round;rx:7px}#chartlet-993d7890224c2061 .chartlet-flow-start{stroke-width:2}#chartlet-993d7890224c2061 .chartlet-flow-end{stroke-width:3}#chartlet-993d7890224c2061 .chartlet-flow-external{stroke-dasharray:5 3}#chartlet-993d7890224c2061 .chartlet-flow-inner{stroke:var(--chartlet-role-blue);stroke-width:1}#chartlet-993d7890224c2061 .chartlet-flow-label{font-size:13px;font-weight:600;fill:var(--chartlet-text)}#chartlet-993d7890224c2061 .chartlet-flow-sublabel{font-size:11px;fill:var(--chartlet-muted)}#chartlet-993d7890224c2061 .chartlet-flow-edge{fill:none;stroke:var(--chartlet-zero);stroke-width:1.4;stroke-linejoin:round}#chartlet-993d7890224c2061 .chartlet-flow-dashed{stroke-dasharray:5 4}#chartlet-993d7890224c2061 .chartlet-flow-dotted{stroke-dasharray:1 4;stroke-linecap:round}#chartlet-993d7890224c2061 .chartlet-flow-main{stroke:var(--chartlet-accent);stroke-width:2.2}#chartlet-993d7890224c2061 .chartlet-flow-head{fill:var(--chartlet-zero);stroke:var(--chartlet-zero);stroke-width:1;stroke-linejoin:round}#chartlet-993d7890224c2061 .chartlet-flow-main-head{fill:var(--chartlet-accent);stroke:var(--chartlet-accent)}#chartlet-993d7890224c2061 .chartlet-flow-lane{fill:var(--chartlet-lane);stroke:var(--chartlet-grid);stroke-width:1}#chartlet-993d7890224c2061 .chartlet-flow-lane-alt{fill:var(--chartlet-background)}#chartlet-993d7890224c2061 .chartlet-flow-lane-head{fill:var(--chartlet-lane-head);stroke:none}#chartlet-993d7890224c2061 .chartlet-flow-lane-label{font-size:11px;font-weight:650;fill:var(--chartlet-muted);letter-spacing:.04em}#chartlet-993d7890224c2061 .chartlet-flow-group{fill:var(--chartlet-accent);fill-opacity:.04;stroke:var(--chartlet-zero);stroke-width:1;stroke-dasharray:4 3;rx:10px}#chartlet-993d7890224c2061 .chartlet-flow-group-label{font-size:11px;font-weight:600;fill:var(--chartlet-muted)}#chartlet-993d7890224c2061 .chartlet-arch-head{fill:var(--chartlet-role-violet-fill);stroke:var(--chartlet-role-violet);stroke-width:1.5}#chartlet-993d7890224c2061 .chartlet-arch-dot{fill:var(--chartlet-role-blue);stroke:none}</style><rect x="332.287" y="260.907" width="458.95" height="692.328" class="chartlet-flow-group"/><text x="340.287" y="273.907" text-anchor="start" class="chartlet-flow-group-label">Data center</text><rect x="344.287" y="422.341" width="434.95" height="518.894" class="chartlet-flow-group"/><text x="352.287" y="435.341" text-anchor="start" class="chartlet-flow-group-label">Application network</text><rect x="445.337" y="829.235" width="321.9" height="100" class="chartlet-flow-group"/><text x="453.337" y="842.235" text-anchor="start" class="chartlet-flow-group-label">Data zone</text><g class="chartlet-f chartlet-f-0 chartlet-f-1"><polyline points="540.287,66 540.287,122.363" class="chartlet-flow-edge chartlet-flow-main"><title>Teacher, parent → Browser: uses</title></polyline><polyline points="536.787,122.363 540.287,130.363 543.787,122.363 536.787,122.363" class="chartlet-flow-head chartlet-flow-main-head"/></g><g class="chartlet-f chartlet-f-1 chartlet-f-2"><polyline points="540.287,178.363 540.287,280.907" class="chartlet-flow-edge chartlet-flow-main"><title>Browser → Reverse proxy: calls [HTTPS]</title></polyline><polyline points="536.787,280.907 540.287,288.907 543.787,280.907 536.787,280.907" class="chartlet-flow-head chartlet-flow-main-head"/></g><g class="chartlet-f chartlet-f-2 chartlet-f-3"><polyline points="540.287,356.907 540.287,442.341" class="chartlet-flow-edge chartlet-flow-main"><title>Reverse proxy → Web / BFF: forwards</title></polyline><polyline points="536.787,442.341 540.287,450.341 543.787,442.341 536.787,442.341" class="chartlet-flow-head chartlet-flow-main-head"/></g><g class="chartlet-f chartlet-f-3 chartlet-f-4"><polyline points="516.287,500.341 516.287,564.778 408.287,564.778 408.287,582.553" class="chartlet-flow-edge"><title>Web / BFF → Sign-in: signs in [OIDC]</title></polyline><polyline points="404.787,582.553 408.287,590.553 411.787,582.553 404.787,582.553" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-f-3 chartlet-f-5"><polyline points="540.287,500.341 540.287,591.553" class="chartlet-flow-edge chartlet-flow-main"><title>Web / BFF → Domain API: queries [user context]</title></polyline><polyline points="536.787,591.553 540.287,599.553 543.787,591.553 536.787,591.553" class="chartlet-flow-head chartlet-flow-main-head"/></g><g class="chartlet-f chartlet-f-5 chartlet-f-6"><polyline points="540.287,649.553 540.287,849.235" class="chartlet-flow-edge chartlet-flow-main"><title>Domain API → Domain data: reads, writes [SQL/TLS]</title></polyline><polyline points="536.787,849.235 540.287,857.235 543.787,849.235 536.787,849.235" class="chartlet-flow-head chartlet-flow-main-head"/></g><g class="chartlet-f chartlet-f-5 chartlet-f-7"><polyline points="562.287,649.553 562.287,801.389 703.237,801.389 703.237,849.235" class="chartlet-flow-edge"><title>Domain API → Audit log: logs</title></polyline><polyline points="699.737,849.235 703.237,857.235 706.737,849.235 699.737,849.235" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-f-5 chartlet-f-9"><polyline points="680.712,179.363 680.712,564.778 564.287,564.778 564.287,591.553" class="chartlet-flow-edge"><title>School records → Domain API: master data [REST/JSON]</title></polyline><polyline points="560.787,591.553 564.287,599.553 567.787,591.553 560.787,591.553" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-f-5 chartlet-f-10"><polyline points="584.287,649.553 584.287,790.65 859.237,790.65 859.237,1004.225 815.713,1004.225 815.713,1031" class="chartlet-flow-edge chartlet-flow-dashed"><title>Domain API → SIEM / SOC: events [Syslog]</title></polyline><polyline points="812.213,1031 815.713,1039 819.213,1031 812.213,1031" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-f-6 chartlet-f-8"><polyline points="540.287,917.235 540.287,1004.225 496.763,1004.225 496.763,1022" class="chartlet-flow-edge chartlet-flow-dashed"><title>Domain data → Backup: backs up</title></polyline><polyline points="493.263,1022 496.763,1030 500.263,1022 493.263,1022" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-n-0 chartlet-f-0 chartlet-f-1"></g><g class="chartlet-f chartlet-n-1 chartlet-f-0 chartlet-f-1 chartlet-f-2"></g><g class="chartlet-f chartlet-n-2 chartlet-f-1 chartlet-f-2 chartlet-f-3"></g><g class="chartlet-f chartlet-n-3 chartlet-f-2 chartlet-f-3 chartlet-f-4 chartlet-f-5"></g><g class="chartlet-f chartlet-n-4 chartlet-f-3 chartlet-f-4"></g><g class="chartlet-f chartlet-n-5 chartlet-f-3 chartlet-f-5 chartlet-f-6 chartlet-f-7 chartlet-f-9 chartlet-f-10"></g><g class="chartlet-f chartlet-n-6 chartlet-f-5 chartlet-f-6 chartlet-f-8"></g><g class="chartlet-f chartlet-n-7 chartlet-f-5 chartlet-f-7"></g><g class="chartlet-f chartlet-n-8 chartlet-f-6 chartlet-f-8"></g><g class="chartlet-f chartlet-n-9 chartlet-f-5 chartlet-f-9"></g><g class="chartlet-f chartlet-n-10 chartlet-f-5 chartlet-f-10"></g><g class="chartlet-f chartlet-f-0 chartlet-f-1"><rect x="544.287" y="71" width="36.88" height="21" class="chartlet-diagram-chip"/><text x="549.287" y="85" text-anchor="start" class="chartlet-diagram-chip-text">uses</text></g><g class="chartlet-f chartlet-f-1 chartlet-f-2"><rect x="544.287" y="183.363" width="63.64" height="36" class="chartlet-diagram-chip"/><text x="549.287" y="197.363" text-anchor="start" class="chartlet-diagram-chip-text">calls</text><text x="549.287" y="212.363" text-anchor="start" class="chartlet-diagram-chip-text">[HTTPS]</text></g><g class="chartlet-f chartlet-f-2 chartlet-f-3"><rect x="544.287" y="361.907" width="67.84" height="21" class="chartlet-diagram-chip"/><text x="549.287" y="375.907" text-anchor="start" class="chartlet-diagram-chip-text">forwards</text></g><g class="chartlet-f chartlet-f-3 chartlet-f-4"><rect x="457.647" y="505.341" width="54.64" height="36" class="chartlet-diagram-chip"/><text x="507.287" y="519.341" text-anchor="end" class="chartlet-diagram-chip-text">signs in</text><text x="507.287" y="534.341" text-anchor="end" class="chartlet-diagram-chip-text">[OIDC]</text></g><g class="chartlet-f chartlet-f-3 chartlet-f-5"><rect x="544.287" y="505.341" width="101.2" height="36" class="chartlet-diagram-chip"/><text x="549.287" y="519.341" text-anchor="start" class="chartlet-diagram-chip-text">queries</text><text x="549.287" y="534.341" text-anchor="start" class="chartlet-diagram-chip-text">[user context]</text></g><g class="chartlet-f chartlet-f-5 chartlet-f-6"><rect x="443.967" y="661.553" width="92.32" height="36" class="chartlet-diagram-chip"/><text x="531.287" y="675.553" text-anchor="end" class="chartlet-diagram-chip-text">reads, writes</text><text x="531.287" y="690.553" text-anchor="end" class="chartlet-diagram-chip-text">[SQL/TLS]</text></g><g class="chartlet-f chartlet-f-5 chartlet-f-7"><rect x="615.882" y="832.235" width="33.76" height="21" class="chartlet-diagram-chip"/><text x="632.762" y="846.235" text-anchor="middle" class="chartlet-diagram-chip-text">logs</text></g><g class="chartlet-f chartlet-f-5 chartlet-f-9"><rect x="684.712" y="184.363" width="94.48" height="36" class="chartlet-diagram-chip"/><text x="689.712" y="198.363" text-anchor="start" class="chartlet-diagram-chip-text">master data</text><text x="689.712" y="213.363" text-anchor="start" class="chartlet-diagram-chip-text">[REST/JSON]</text></g><g class="chartlet-f chartlet-f-5 chartlet-f-10"><rect x="588.287" y="654.553" width="61.96" height="36" class="chartlet-diagram-chip"/><text x="593.287" y="668.553" text-anchor="start" class="chartlet-diagram-chip-text">events</text><text x="593.287" y="683.553" text-anchor="start" class="chartlet-diagram-chip-text">[Syslog]</text></g><g class="chartlet-f chartlet-f-6 chartlet-f-8"><rect x="544.287" y="956.235" width="60.88" height="21" class="chartlet-diagram-chip"/><text x="549.287" y="970.235" text-anchor="start" class="chartlet-diagram-chip-text">backs up</text></g><g class="chartlet-f chartlet-n-0 chartlet-f-0 chartlet-f-1"><rect x="476.222" y="14.5" width="128.13" height="54" class="chartlet-diagram-shadow"/><rect x="476.222" y="12" width="128.13" height="54" class="chartlet-flow-node chartlet-role-violet"><title>Teacher, parent</title></rect><circle cx="540.287" cy="23" r="6" class="chartlet-arch-head"/><text x="540.287" y="51.5" text-anchor="middle" class="chartlet-flow-label">Teacher, parent</text></g><g class="chartlet-f chartlet-n-1 chartlet-f-0 chartlet-f-1 chartlet-f-2"><rect x="488.287" y="132.863" width="104" height="48" class="chartlet-diagram-shadow"/><rect x="488.287" y="130.363" width="104" height="48" class="chartlet-flow-node chartlet-role-blue"><title>Browser</title></rect><line x1="488.287" y1="142.363" x2="592.287" y2="142.363" class="chartlet-flow-inner"/><circle cx="496.287" cy="136.363" r="1.8" class="chartlet-arch-dot"/><circle cx="502.287" cy="136.363" r="1.8" class="chartlet-arch-dot"/><circle cx="508.287" cy="136.363" r="1.8" class="chartlet-arch-dot"/><text x="540.287" y="164.863" text-anchor="middle" class="chartlet-flow-label">Browser</text></g><g class="chartlet-f chartlet-n-2 chartlet-f-1 chartlet-f-2 chartlet-f-3"><polyline points="481.812,291.407 598.762,291.407 598.762,332.207 540.287,359.407 481.812,332.207 481.812,291.407" class="chartlet-diagram-shadow"/><polyline points="481.812,288.907 598.762,288.907 598.762,329.707 540.287,356.907 481.812,329.707 481.812,288.907" class="chartlet-flow-node chartlet-role-red"><title>Reverse proxy – TLS 1.3, WAF</title></polyline><text x="540.287" y="314.407" text-anchor="middle" class="chartlet-flow-label">Reverse proxy</text><text x="540.287" y="328.407" text-anchor="middle" class="chartlet-flow-sublabel">TLS 1.3, WAF</text></g><g class="chartlet-f chartlet-n-3 chartlet-f-2 chartlet-f-3 chartlet-f-4 chartlet-f-5"><rect x="488.287" y="452.841" width="104" height="50" class="chartlet-diagram-shadow"/><rect x="488.287" y="450.341" width="104" height="50" class="chartlet-flow-node chartlet-role-blue"><title>Web / BFF – SvelteKit</title></rect><text x="540.287" y="472.841" text-anchor="middle" class="chartlet-flow-label">Web / BFF</text><text x="540.287" y="486.841" text-anchor="middle" class="chartlet-flow-sublabel">SvelteKit</text></g><g class="chartlet-f chartlet-n-4 chartlet-f-3 chartlet-f-4"><polyline points="356.287,593.053 460.287,593.053 460.287,633.853 408.287,661.053 356.287,633.853 356.287,593.053" class="chartlet-diagram-shadow"/><polyline points="356.287,590.553 460.287,590.553 460.287,631.353 408.287,658.553 356.287,631.353 356.287,590.553" class="chartlet-flow-node chartlet-role-red"><title>Sign-in – Keycloak, OIDC</title></polyline><text x="408.287" y="616.053" text-anchor="middle" class="chartlet-flow-label">Sign-in</text><text x="408.287" y="630.053" text-anchor="middle" class="chartlet-flow-sublabel">Keycloak, OIDC</text></g><g class="chartlet-f chartlet-n-5 chartlet-f-3 chartlet-f-5 chartlet-f-6 chartlet-f-7 chartlet-f-9 chartlet-f-10"><rect x="488.287" y="602.053" width="104" height="50" class="chartlet-diagram-shadow"/><rect x="488.287" y="599.553" width="104" height="50" class="chartlet-flow-node chartlet-role-blue"><title>Domain API – Rust</title></rect><text x="540.287" y="622.053" text-anchor="middle" class="chartlet-flow-label">Domain API</text><text x="540.287" y="636.053" text-anchor="middle" class="chartlet-flow-sublabel">Rust</text></g><g class="chartlet-f chartlet-n-6 chartlet-f-5 chartlet-f-6 chartlet-f-8"><polyline points="457.337,864.735 457.337,914.735 460.163,916.029 468.45,917.235 481.632,918.27 498.812,919.065 518.818,919.564 540.287,919.735 561.756,919.564 581.762,919.065 598.941,918.27 612.123,917.235 620.41,916.029 623.237,914.735 623.237,864.735 620.41,863.441 612.123,862.235 598.941,861.199 581.762,860.405 561.756,859.905 540.287,859.735 518.818,859.905 498.812,860.405 481.632,861.199 468.45,862.235 460.163,863.441 457.337,864.735 457.337,864.735" class="chartlet-diagram-shadow"/><polyline points="457.337,862.235 457.337,912.235 460.163,913.529 468.45,914.735 481.632,915.77 498.812,916.565 518.818,917.064 540.287,917.235 561.756,917.064 581.762,916.565 598.941,915.77 612.123,914.735 620.41,913.529 623.237,912.235 623.237,862.235 620.41,860.941 612.123,859.735 598.941,858.699 581.762,857.905 561.756,857.405 540.287,857.235 518.818,857.405 498.812,857.905 481.632,858.699 468.45,859.735 460.163,860.941 457.337,862.235 457.337,862.235" class="chartlet-flow-node chartlet-role-teal"><title>Domain data – Postgres, RLS per tenant</title></polyline><polyline points="457.337,862.235 460.163,863.529 468.45,864.735 481.632,865.77 498.812,866.565 518.818,867.064 540.287,867.235 561.756,867.064 581.762,866.565 598.941,865.77 612.123,864.735 620.41,863.529 623.237,862.235" class="chartlet-diagram-rim"/><text x="540.287" y="887.735" text-anchor="middle" class="chartlet-flow-label">Domain data</text><text x="540.287" y="901.735" text-anchor="middle" class="chartlet-flow-sublabel">Postgres, RLS per tenant</text></g><g class="chartlet-f chartlet-n-7 chartlet-f-5 chartlet-f-7"><polyline points="651.237,864.735 651.237,914.735 653.008,916.029 658.203,917.235 666.467,918.27 677.237,919.065 689.778,919.564 703.237,919.735 716.695,919.564 729.237,919.065 740.006,918.27 748.27,917.235 753.465,916.029 755.237,914.735 755.237,864.735 753.465,863.441 748.27,862.235 740.006,861.199 729.237,860.405 716.695,859.905 703.237,859.735 689.778,859.905 677.237,860.405 666.467,861.199 658.203,862.235 653.008,863.441 651.237,864.735 651.237,864.735" class="chartlet-diagram-shadow"/><polyline points="651.237,862.235 651.237,912.235 653.008,913.529 658.203,914.735 666.467,915.77 677.237,916.565 689.778,917.064 703.237,917.235 716.695,917.064 729.237,916.565 740.006,915.77 748.27,914.735 753.465,913.529 755.237,912.235 755.237,862.235 753.465,860.941 748.27,859.735 740.006,858.699 729.237,857.905 716.695,857.405 703.237,857.235 689.778,857.405 677.237,857.905 666.467,858.699 658.203,859.735 653.008,860.941 651.237,862.235 651.237,862.235" class="chartlet-flow-node chartlet-role-teal"><title>Audit log – append only</title></polyline><polyline points="651.237,862.235 653.008,863.529 658.203,864.735 666.467,865.77 677.237,866.565 689.778,867.064 703.237,867.235 716.695,867.064 729.237,866.565 740.006,865.77 748.27,864.735 753.465,863.529 755.237,862.235" class="chartlet-diagram-rim"/><text x="703.237" y="887.735" text-anchor="middle" class="chartlet-flow-label">Audit log</text><text x="703.237" y="901.735" text-anchor="middle" class="chartlet-flow-sublabel">append only</text></g><g class="chartlet-f chartlet-n-8 chartlet-f-6 chartlet-f-8"><polyline points="436.763,1032.5 556.763,1032.5 548.763,1086.5 444.763,1086.5 436.763,1032.5" class="chartlet-diagram-shadow"/><polyline points="436.763,1030 556.763,1030 548.763,1084 444.763,1084 436.763,1030" class="chartlet-flow-node chartlet-role-teal"><title>Backup – second site</title></polyline><text x="496.763" y="1054.5" text-anchor="middle" class="chartlet-flow-label">Backup</text><text x="496.763" y="1068.5" text-anchor="middle" class="chartlet-flow-sublabel">second site</text></g><g class="chartlet-f chartlet-n-9 chartlet-f-5 chartlet-f-9"><rect x="620.287" y="131.863" width="120.85" height="50" class="chartlet-diagram-shadow"/><rect x="620.287" y="129.363" width="120.85" height="50" class="chartlet-flow-node chartlet-flow-external chartlet-role-gray"><title>School records – legacy system</title></rect><text x="680.712" y="151.863" text-anchor="middle" class="chartlet-flow-label">School records</text><text x="680.712" y="165.863" text-anchor="middle" class="chartlet-flow-sublabel">legacy system</text></g><g class="chartlet-f chartlet-n-10 chartlet-f-5 chartlet-f-10"><rect x="763.713" y="1041.5" width="104" height="36" class="chartlet-diagram-shadow"/><rect x="763.713" y="1039" width="104" height="36" class="chartlet-flow-node chartlet-flow-external chartlet-role-gray"><title>SIEM / SOC</title></rect><text x="815.713" y="1061.5" text-anchor="middle" class="chartlet-flow-label">SIEM / SOC</text></g></svg><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-0" for="chartlet-993d7890224c2061-focus-0"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-1" for="chartlet-993d7890224c2061-focus-1"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-2" for="chartlet-993d7890224c2061-focus-2"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-3" for="chartlet-993d7890224c2061-focus-3"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-4" for="chartlet-993d7890224c2061-focus-4"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-5" for="chartlet-993d7890224c2061-focus-5"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-6" for="chartlet-993d7890224c2061-focus-6"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-7" for="chartlet-993d7890224c2061-focus-7"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-8" for="chartlet-993d7890224c2061-focus-8"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-9" for="chartlet-993d7890224c2061-focus-9"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-hs-10" for="chartlet-993d7890224c2061-focus-10"></label></div></div><div class="chartlet-variant-mobile"><div class="chartlet-stage"><svg xmlns="http://www.w3.org/2000/svg" width="464" height="1180" viewBox="0 0 464 1180" id="chartlet-993d7890224c2061-m" role="img" aria-labelledby="chartlet-993d7890224c2061-m-title chartlet-993d7890224c2061-m-description" class="chartlet-root"><title id="chartlet-993d7890224c2061-m-title">Multi-tenant line-of-business application</title><desc id="chartlet-993d7890224c2061-m-description">Architecture diagram with 11 components and 10 connections in 3 boundaries. Data center: Reverse proxy, Application network. Application network (in Data center): Web / BFF, Sign-in, Domain API, Data zone. Data zone (in Application network): Domain data, Audit log. Main path: Teacher, parent → Browser → Reverse proxy → Web / BFF → Domain API → Domain data. Most connected: Domain API (5 connections). Nothing leads into Teacher, parent and School records. Teacher, parent (person): connects to Browser (uses). Browser (frontend): connects to Reverse proxy (calls, via HTTPS). School records (external system): connects to Domain API (master data, via REST/JSON). Reverse proxy (security): connects to Web / BFF (forwards). Web / BFF (service): connects to Sign-in (signs in, via OIDC) and Domain API (queries, via user context). Sign-in (security): no outgoing connection. Domain API (service): connects to Domain data (reads, writes, via SQL/TLS), Audit log (logs) and SIEM / SOC (events, via Syslog). Domain data (database): connects to Backup (backs up). Audit log (database): no outgoing connection. Backup (storage): no outgoing connection. SIEM / SOC (external system): no outgoing connection.</desc><style>.chartlet-root{--chartlet-text:#172033;--chartlet-muted:#344054;--chartlet-grid:#d9dee8;--chartlet-zero:#667085;--chartlet-accent:#2563eb;--chartlet-background:#fff;--chartlet-color-1:#2563eb;--chartlet-color-2:#c2410c;--chartlet-color-3:#475569;--chartlet-color-4:#111827;max-width:100%;height:auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif;color:var(--chartlet-text)}#chartlet-993d7890224c2061-m .chartlet-title{font-size:22px;font-weight:650;fill:var(--chartlet-text)}#chartlet-993d7890224c2061-m .chartlet-label,#chartlet-993d7890224c2061-m .chartlet-tick,#chartlet-993d7890224c2061-m .chartlet-value,#chartlet-993d7890224c2061-m .chartlet-value-inverse,#chartlet-993d7890224c2061-m .chartlet-axis-title{font-size:12px;fill:var(--chartlet-muted)}#chartlet-993d7890224c2061-m .chartlet-value,#chartlet-993d7890224c2061-m .chartlet-value-inverse{font-weight:600}#chartlet-993d7890224c2061-m .chartlet-value{fill:var(--chartlet-text)}#chartlet-993d7890224c2061-m .chartlet-value-inverse{fill:var(--chartlet-background)}#chartlet-993d7890224c2061-m .chartlet-axis-title{font-weight:600}#chartlet-993d7890224c2061-m .chartlet-grid{stroke:var(--chartlet-grid);stroke-width:1}#chartlet-993d7890224c2061-m .chartlet-zero{stroke:var(--chartlet-zero);stroke-width:1.5}#chartlet-993d7890224c2061-m .chartlet-bar,#chartlet-993d7890224c2061-m .chartlet-point{fill:var(--chartlet-accent)}#chartlet-993d7890224c2061-m .chartlet-line{fill:none;stroke:var(--chartlet-accent);stroke-width:3;stroke-linecap:round;stroke-linejoin:round}#chartlet-993d7890224c2061-m .chartlet-background{fill:var(--chartlet-background)}#chartlet-993d7890224c2061-m .chartlet-title-small{font-size:18px}.chartlet-root{--chartlet-node:#eef3fd;--chartlet-lane:#f7f9fc;--chartlet-lane-head:#eef1f6;--chartlet-shadow:rgba(16,24,40,.09);--chartlet-role-blue:#2563eb;--chartlet-role-blue-fill:#eef3fd;--chartlet-role-green:#15803d;--chartlet-role-green-fill:#ecfdf3;--chartlet-role-amber:#b45309;--chartlet-role-amber-fill:#fff7e8;--chartlet-role-teal:#0f766e;--chartlet-role-teal-fill:#e9faf7;--chartlet-role-violet:#6d28d9;--chartlet-role-violet-fill:#f3efff;--chartlet-role-gray:#667085;--chartlet-role-gray-fill:#f7f8fa;--chartlet-role-red:#b42318;--chartlet-role-red-fill:#fef3f2}.chartlet-root.chartlet-theme-dark{--chartlet-node:#1a2436;--chartlet-lane:#121925;--chartlet-lane-head:#18212f;--chartlet-shadow:rgba(0,0,0,.45);--chartlet-role-blue:#7ea6ff;--chartlet-role-blue-fill:#1a2436;--chartlet-role-green:#4ade80;--chartlet-role-green-fill:#132a1d;--chartlet-role-amber:#fbbf24;--chartlet-role-amber-fill:#2b2210;--chartlet-role-teal:#2dd4bf;--chartlet-role-teal-fill:#0f2a27;--chartlet-role-violet:#b69cff;--chartlet-role-violet-fill:#231c38;--chartlet-role-gray:#9aa7bd;--chartlet-role-gray-fill:#161d29;--chartlet-role-red:#f97066;--chartlet-role-red-fill:#2d1616}#chartlet-993d7890224c2061-m .chartlet-role-blue{fill:var(--chartlet-role-blue-fill);stroke:var(--chartlet-role-blue)}#chartlet-993d7890224c2061-m .chartlet-role-green{fill:var(--chartlet-role-green-fill);stroke:var(--chartlet-role-green)}#chartlet-993d7890224c2061-m .chartlet-role-amber{fill:var(--chartlet-role-amber-fill);stroke:var(--chartlet-role-amber)}#chartlet-993d7890224c2061-m .chartlet-role-teal{fill:var(--chartlet-role-teal-fill);stroke:var(--chartlet-role-teal)}#chartlet-993d7890224c2061-m .chartlet-role-violet{fill:var(--chartlet-role-violet-fill);stroke:var(--chartlet-role-violet)}#chartlet-993d7890224c2061-m .chartlet-role-gray{fill:var(--chartlet-role-gray-fill);stroke:var(--chartlet-role-gray)}#chartlet-993d7890224c2061-m .chartlet-role-red{fill:var(--chartlet-role-red-fill);stroke:var(--chartlet-role-red)}#chartlet-993d7890224c2061-m .chartlet-diagram-rim{fill:none;stroke:var(--chartlet-role-teal);stroke-width:1.5}#chartlet-993d7890224c2061-m .chartlet-diagram-shadow{fill:var(--chartlet-shadow);stroke:none;rx:7px}#chartlet-993d7890224c2061-m .chartlet-diagram-chip{fill:var(--chartlet-background);stroke:var(--chartlet-grid);stroke-width:1;rx:4px}#chartlet-993d7890224c2061-m .chartlet-diagram-chip-text{font-size:12px;fill:var(--chartlet-text)}#chartlet-993d7890224c2061-m .chartlet-diagram-badge{fill:var(--chartlet-accent);stroke:var(--chartlet-background);stroke-width:2}#chartlet-993d7890224c2061-m .chartlet-diagram-badge-text{font-size:10px;font-weight:700;fill:var(--chartlet-background)}#chartlet-993d7890224c2061-m .chartlet-flow-node{stroke-width:1.5;stroke-linejoin:round;rx:7px}#chartlet-993d7890224c2061-m .chartlet-flow-start{stroke-width:2}#chartlet-993d7890224c2061-m .chartlet-flow-end{stroke-width:3}#chartlet-993d7890224c2061-m .chartlet-flow-external{stroke-dasharray:5 3}#chartlet-993d7890224c2061-m .chartlet-flow-inner{stroke:var(--chartlet-role-blue);stroke-width:1}#chartlet-993d7890224c2061-m .chartlet-flow-label{font-size:13px;font-weight:600;fill:var(--chartlet-text)}#chartlet-993d7890224c2061-m .chartlet-flow-sublabel{font-size:11px;fill:var(--chartlet-muted)}#chartlet-993d7890224c2061-m .chartlet-flow-edge{fill:none;stroke:var(--chartlet-zero);stroke-width:1.4;stroke-linejoin:round}#chartlet-993d7890224c2061-m .chartlet-flow-dashed{stroke-dasharray:5 4}#chartlet-993d7890224c2061-m .chartlet-flow-dotted{stroke-dasharray:1 4;stroke-linecap:round}#chartlet-993d7890224c2061-m .chartlet-flow-main{stroke:var(--chartlet-accent);stroke-width:2.2}#chartlet-993d7890224c2061-m .chartlet-flow-head{fill:var(--chartlet-zero);stroke:var(--chartlet-zero);stroke-width:1;stroke-linejoin:round}#chartlet-993d7890224c2061-m .chartlet-flow-main-head{fill:var(--chartlet-accent);stroke:var(--chartlet-accent)}#chartlet-993d7890224c2061-m .chartlet-flow-lane{fill:var(--chartlet-lane);stroke:var(--chartlet-grid);stroke-width:1}#chartlet-993d7890224c2061-m .chartlet-flow-lane-alt{fill:var(--chartlet-background)}#chartlet-993d7890224c2061-m .chartlet-flow-lane-head{fill:var(--chartlet-lane-head);stroke:none}#chartlet-993d7890224c2061-m .chartlet-flow-lane-label{font-size:11px;font-weight:650;fill:var(--chartlet-muted);letter-spacing:.04em}#chartlet-993d7890224c2061-m .chartlet-flow-group{fill:var(--chartlet-accent);fill-opacity:.04;stroke:var(--chartlet-zero);stroke-width:1;stroke-dasharray:4 3;rx:10px}#chartlet-993d7890224c2061-m .chartlet-flow-group-label{font-size:11px;font-weight:600;fill:var(--chartlet-muted)}#chartlet-993d7890224c2061-m .chartlet-arch-head{fill:var(--chartlet-role-violet-fill);stroke:var(--chartlet-role-violet);stroke-width:1.5}#chartlet-993d7890224c2061-m .chartlet-arch-dot{fill:var(--chartlet-role-blue);stroke:none}</style><rect x="13.121" y="301.707" width="381.65" height="725.788" class="chartlet-flow-group"/><text x="21.121" y="314.707" text-anchor="start" class="chartlet-flow-group-label">Data center</text><rect x="25.121" y="467.897" width="357.65" height="547.598" class="chartlet-flow-group"/><text x="33.121" y="480.897" text-anchor="start" class="chartlet-flow-group-label">Application network</text><rect x="141.081" y="889.495" width="229.69" height="114" class="chartlet-flow-group"/><text x="149.081" y="902.495" text-anchor="start" class="chartlet-flow-group-label">Data zone</text><g class="chartlet-f chartlet-f-0 chartlet-f-1"><polyline points="204.796,82 204.796,149.588" class="chartlet-flow-edge chartlet-flow-main"><title>Teacher, parent → Browser: uses</title></polyline><polyline points="201.296,149.588 204.796,157.588 208.296,149.588 201.296,149.588" class="chartlet-flow-head chartlet-flow-main-head"/></g><g class="chartlet-f chartlet-f-1 chartlet-f-2"><polyline points="204.796,205.588 204.796,321.707" class="chartlet-flow-edge chartlet-flow-main"><title>Browser → Reverse proxy: calls [HTTPS]</title></polyline><polyline points="201.296,321.707 204.796,329.707 208.296,321.707 201.296,321.707" class="chartlet-flow-head chartlet-flow-main-head"/></g><g class="chartlet-f chartlet-f-2 chartlet-f-3"><polyline points="204.796,397.707 204.796,487.897" class="chartlet-flow-edge chartlet-flow-main"><title>Reverse proxy → Web / BFF: forwards</title></polyline><polyline points="201.296,487.897 204.796,495.897 208.296,487.897 201.296,487.897" class="chartlet-flow-head chartlet-flow-main-head"/></g><g class="chartlet-f chartlet-f-3 chartlet-f-4"><polyline points="180.796,545.897 180.796,613.614 89.051,613.614 89.051,632.701" class="chartlet-flow-edge"><title>Web / BFF → Sign-in: signs in [OIDC]</title></polyline><polyline points="85.551,632.701 89.051,640.701 92.551,632.701 85.551,632.701" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-f-3 chartlet-f-5"><polyline points="204.796,545.897 204.796,641.701" class="chartlet-flow-edge chartlet-flow-main"><title>Web / BFF → Domain API: queries [user context]</title></polyline><polyline points="201.296,641.701 204.796,649.701 208.296,641.701 201.296,641.701" class="chartlet-flow-head chartlet-flow-main-head"/></g><g class="chartlet-f chartlet-f-5 chartlet-f-6"><polyline points="204.796,699.701 204.796,909.495" class="chartlet-flow-edge chartlet-flow-main"><title>Domain API → Domain data: reads, writes [SQL/TLS]</title></polyline><polyline points="201.296,909.495 204.796,917.495 208.296,909.495 201.296,909.495" class="chartlet-flow-head chartlet-flow-main-head"/></g><g class="chartlet-f chartlet-f-5 chartlet-f-7"><polyline points="224.704,699.701 224.704,858.807 315.641,858.807 315.641,916.495" class="chartlet-flow-edge"><title>Domain API → Audit log: logs</title></polyline><polyline points="312.141,916.495 315.641,924.495 319.141,916.495 312.141,916.495" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-f-5 chartlet-f-9"><polyline points="312.361,214.588 312.361,613.614 228.796,613.614 228.796,641.701" class="chartlet-flow-edge"><title>School records → Domain API: master data [REST/JSON]</title></polyline><polyline points="225.296,641.701 228.796,649.701 232.296,641.701 225.296,641.701" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-f-5 chartlet-f-10"><polyline points="244.611,699.701 244.611,847.521 426.771,847.521 426.771,1082.913 401.504,1082.913 401.504,1111" class="chartlet-flow-edge chartlet-flow-dashed"><title>Domain API → SIEM / SOC: events [Syslog]</title></polyline><polyline points="398.004,1111 401.504,1119 405.004,1111 398.004,1111" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-f-6 chartlet-f-8"><polyline points="204.796,991.495 204.796,1082.913 179.529,1082.913 179.529,1102" class="chartlet-flow-edge chartlet-flow-dashed"><title>Domain data → Backup: backs up</title></polyline><polyline points="176.029,1102 179.529,1110 183.029,1102 176.029,1102" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-n-0 chartlet-f-0 chartlet-f-1"></g><g class="chartlet-f chartlet-n-1 chartlet-f-0 chartlet-f-1 chartlet-f-2"></g><g class="chartlet-f chartlet-n-2 chartlet-f-1 chartlet-f-2 chartlet-f-3"></g><g class="chartlet-f chartlet-n-3 chartlet-f-2 chartlet-f-3 chartlet-f-4 chartlet-f-5"></g><g class="chartlet-f chartlet-n-4 chartlet-f-3 chartlet-f-4"></g><g class="chartlet-f chartlet-n-5 chartlet-f-3 chartlet-f-5 chartlet-f-6 chartlet-f-7 chartlet-f-9 chartlet-f-10"></g><g class="chartlet-f chartlet-n-6 chartlet-f-5 chartlet-f-6 chartlet-f-8"></g><g class="chartlet-f chartlet-n-7 chartlet-f-5 chartlet-f-7"></g><g class="chartlet-f chartlet-n-8 chartlet-f-6 chartlet-f-8"></g><g class="chartlet-f chartlet-n-9 chartlet-f-5 chartlet-f-9"></g><g class="chartlet-f chartlet-n-10 chartlet-f-5 chartlet-f-10"></g><g class="chartlet-f chartlet-f-0 chartlet-f-1"><rect x="208.796" y="87" width="36.88" height="21" class="chartlet-diagram-chip"/><text x="213.796" y="101" text-anchor="start" class="chartlet-diagram-chip-text">uses</text></g><g class="chartlet-f chartlet-f-1 chartlet-f-2"><rect x="208.796" y="217.588" width="63.64" height="36" class="chartlet-diagram-chip"/><text x="213.796" y="231.588" text-anchor="start" class="chartlet-diagram-chip-text">calls</text><text x="213.796" y="246.588" text-anchor="start" class="chartlet-diagram-chip-text">[HTTPS]</text></g><g class="chartlet-f chartlet-f-2 chartlet-f-3"><rect x="208.796" y="402.707" width="67.84" height="21" class="chartlet-diagram-chip"/><text x="213.796" y="416.707" text-anchor="start" class="chartlet-diagram-chip-text">forwards</text></g><g class="chartlet-f chartlet-f-3 chartlet-f-4"><rect x="122.156" y="550.897" width="54.64" height="36" class="chartlet-diagram-chip"/><text x="171.796" y="564.897" text-anchor="end" class="chartlet-diagram-chip-text">signs in</text><text x="171.796" y="579.897" text-anchor="end" class="chartlet-diagram-chip-text">[OIDC]</text></g><g class="chartlet-f chartlet-f-3 chartlet-f-5"><rect x="208.796" y="550.897" width="101.2" height="36" class="chartlet-diagram-chip"/><text x="213.796" y="564.897" text-anchor="start" class="chartlet-diagram-chip-text">queries</text><text x="213.796" y="579.897" text-anchor="start" class="chartlet-diagram-chip-text">[user context]</text></g><g class="chartlet-f chartlet-f-5 chartlet-f-6"><rect x="108.476" y="711.701" width="92.32" height="36" class="chartlet-diagram-chip"/><text x="195.796" y="725.701" text-anchor="end" class="chartlet-diagram-chip-text">reads, writes</text><text x="195.796" y="740.701" text-anchor="end" class="chartlet-diagram-chip-text">[SQL/TLS]</text></g><g class="chartlet-f chartlet-f-5 chartlet-f-7"><rect x="253.293" y="862.807" width="33.76" height="21" class="chartlet-diagram-chip"/><text x="270.173" y="876.807" text-anchor="middle" class="chartlet-diagram-chip-text">logs</text></g><g class="chartlet-f chartlet-f-5 chartlet-f-9"><rect x="316.361" y="219.588" width="94.48" height="36" class="chartlet-diagram-chip"/><text x="321.361" y="233.588" text-anchor="start" class="chartlet-diagram-chip-text">master data</text><text x="321.361" y="248.588" text-anchor="start" class="chartlet-diagram-chip-text">[REST/JSON]</text></g><g class="chartlet-f chartlet-f-5 chartlet-f-10"><rect x="248.611" y="704.701" width="61.96" height="36" class="chartlet-diagram-chip"/><text x="253.611" y="718.701" text-anchor="start" class="chartlet-diagram-chip-text">events</text><text x="253.611" y="733.701" text-anchor="start" class="chartlet-diagram-chip-text">[Syslog]</text></g><g class="chartlet-f chartlet-f-6 chartlet-f-8"><rect x="208.796" y="1030.495" width="60.88" height="21" class="chartlet-diagram-chip"/><text x="213.796" y="1044.495" text-anchor="start" class="chartlet-diagram-chip-text">backs up</text></g><g class="chartlet-f chartlet-n-0 chartlet-f-0 chartlet-f-1"><rect x="164.651" y="14.5" width="80.29" height="70" class="chartlet-diagram-shadow"/><rect x="164.651" y="12" width="80.29" height="70" class="chartlet-flow-node chartlet-role-violet"><title>Teacher, parent</title></rect><circle cx="204.796" cy="23" r="6" class="chartlet-arch-head"/><text x="204.796" y="51.5" text-anchor="middle" class="chartlet-flow-label">Teacher,</text><text x="204.796" y="67.5" text-anchor="middle" class="chartlet-flow-label">parent</text></g><g class="chartlet-f chartlet-n-1 chartlet-f-0 chartlet-f-1 chartlet-f-2"><rect x="164.391" y="160.088" width="80.81" height="48" class="chartlet-diagram-shadow"/><rect x="164.391" y="157.588" width="80.81" height="48" class="chartlet-flow-node chartlet-role-blue"><title>Browser</title></rect><line x1="164.391" y1="169.588" x2="245.201" y2="169.588" class="chartlet-flow-inner"/><circle cx="172.391" cy="163.588" r="1.8" class="chartlet-arch-dot"/><circle cx="178.391" cy="163.588" r="1.8" class="chartlet-arch-dot"/><circle cx="184.391" cy="163.588" r="1.8" class="chartlet-arch-dot"/><text x="204.796" y="192.088" text-anchor="middle" class="chartlet-flow-label">Browser</text></g><g class="chartlet-f chartlet-n-2 chartlet-f-1 chartlet-f-2 chartlet-f-3"><polyline points="146.321,332.207 263.271,332.207 263.271,373.007 204.796,400.207 146.321,373.007 146.321,332.207" class="chartlet-diagram-shadow"/><polyline points="146.321,329.707 263.271,329.707 263.271,370.507 204.796,397.707 146.321,370.507 146.321,329.707" class="chartlet-flow-node chartlet-role-red"><title>Reverse proxy – TLS 1.3, WAF</title></polyline><text x="204.796" y="355.207" text-anchor="middle" class="chartlet-flow-label">Reverse proxy</text><text x="204.796" y="369.207" text-anchor="middle" class="chartlet-flow-sublabel">TLS 1.3, WAF</text></g><g class="chartlet-f chartlet-n-3 chartlet-f-2 chartlet-f-3 chartlet-f-4 chartlet-f-5"><rect x="158.801" y="498.397" width="91.99" height="50" class="chartlet-diagram-shadow"/><rect x="158.801" y="495.897" width="91.99" height="50" class="chartlet-flow-node chartlet-role-blue"><title>Web / BFF – SvelteKit</title></rect><text x="204.796" y="518.397" text-anchor="middle" class="chartlet-flow-label">Web / BFF</text><text x="204.796" y="532.397" text-anchor="middle" class="chartlet-flow-sublabel">SvelteKit</text></g><g class="chartlet-f chartlet-n-4 chartlet-f-3 chartlet-f-4"><polyline points="37.121,643.201 140.981,643.201 140.981,684.001 89.051,711.201 37.121,684.001 37.121,643.201" class="chartlet-diagram-shadow"/><polyline points="37.121,640.701 140.981,640.701 140.981,681.501 89.051,708.701 37.121,681.501 37.121,640.701" class="chartlet-flow-node chartlet-role-red"><title>Sign-in – Keycloak, OIDC</title></polyline><text x="89.051" y="666.201" text-anchor="middle" class="chartlet-flow-label">Sign-in</text><text x="89.051" y="680.201" text-anchor="middle" class="chartlet-flow-sublabel">Keycloak, OIDC</text></g><g class="chartlet-f chartlet-n-5 chartlet-f-3 chartlet-f-5 chartlet-f-6 chartlet-f-7 chartlet-f-9 chartlet-f-10"><rect x="156.981" y="652.201" width="95.63" height="50" class="chartlet-diagram-shadow"/><rect x="156.981" y="649.701" width="95.63" height="50" class="chartlet-flow-node chartlet-role-blue"><title>Domain API – Rust</title></rect><text x="204.796" y="672.201" text-anchor="middle" class="chartlet-flow-label">Domain API</text><text x="204.796" y="686.201" text-anchor="middle" class="chartlet-flow-sublabel">Rust</text></g><g class="chartlet-f chartlet-n-6 chartlet-f-5 chartlet-f-6 chartlet-f-8"><polyline points="153.081,924.995 153.081,988.995 154.844,990.289 160.01,991.495 168.228,992.531 178.939,993.325 191.412,993.825 204.796,993.995 218.181,993.825 230.654,993.325 241.364,992.531 249.583,991.495 254.749,990.289 256.511,988.995 256.511,924.995 254.749,923.701 249.583,922.495 241.364,921.46 230.654,920.665 218.181,920.166 204.796,919.995 191.412,920.166 178.939,920.665 168.228,921.46 160.01,922.495 154.844,923.701 153.081,924.995 153.081,924.995" class="chartlet-diagram-shadow"/><polyline points="153.081,922.495 153.081,986.495 154.844,987.789 160.01,988.995 168.228,990.031 178.939,990.825 191.412,991.325 204.796,991.495 218.181,991.325 230.654,990.825 241.364,990.031 249.583,988.995 254.749,987.789 256.511,986.495 256.511,922.495 254.749,921.201 249.583,919.995 241.364,918.96 230.654,918.165 218.181,917.666 204.796,917.495 191.412,917.666 178.939,918.165 168.228,918.96 160.01,919.995 154.844,921.201 153.081,922.495 153.081,922.495" class="chartlet-flow-node chartlet-role-teal"><title>Domain data – Postgres, RLS per tenant</title></polyline><polyline points="153.081,922.495 154.844,923.789 160.01,924.995 168.228,926.031 178.939,926.825 191.412,927.325 204.796,927.495 218.181,927.325 230.654,926.825 241.364,926.031 249.583,924.995 254.749,923.789 256.511,922.495" class="chartlet-diagram-rim"/><text x="204.796" y="947.995" text-anchor="middle" class="chartlet-flow-label">Domain data</text><text x="204.796" y="961.995" text-anchor="middle" class="chartlet-flow-sublabel">Postgres, RLS</text><text x="204.796" y="975.995" text-anchor="middle" class="chartlet-flow-sublabel">per tenant</text></g><g class="chartlet-f chartlet-n-7 chartlet-f-5 chartlet-f-7"><polyline points="272.511,931.995 272.511,981.995 273.981,983.289 278.29,984.495 285.144,985.531 294.076,986.325 304.478,986.825 315.641,986.995 326.804,986.825 337.206,986.325 346.139,985.531 352.993,984.495 357.302,983.289 358.771,981.995 358.771,931.995 357.302,930.701 352.993,929.495 346.139,928.46 337.206,927.665 326.804,927.166 315.641,926.995 304.478,927.166 294.076,927.665 285.144,928.46 278.29,929.495 273.981,930.701 272.511,931.995 272.511,931.995" class="chartlet-diagram-shadow"/><polyline points="272.511,929.495 272.511,979.495 273.981,980.789 278.29,981.995 285.144,983.031 294.076,983.825 304.478,984.325 315.641,984.495 326.804,984.325 337.206,983.825 346.139,983.031 352.993,981.995 357.302,980.789 358.771,979.495 358.771,929.495 357.302,928.201 352.993,926.995 346.139,925.96 337.206,925.165 326.804,924.666 315.641,924.495 304.478,924.666 294.076,925.165 285.144,925.96 278.29,926.995 273.981,928.201 272.511,929.495 272.511,929.495" class="chartlet-flow-node chartlet-role-teal"><title>Audit log – append only</title></polyline><polyline points="272.511,929.495 273.981,930.789 278.29,931.995 285.144,933.031 294.076,933.825 304.478,934.325 315.641,934.495 326.804,934.325 337.206,933.825 346.139,933.031 352.993,931.995 357.302,930.789 358.771,929.495" class="chartlet-diagram-rim"/><text x="315.641" y="954.995" text-anchor="middle" class="chartlet-flow-label">Audit log</text><text x="315.641" y="968.995" text-anchor="middle" class="chartlet-flow-sublabel">append only</text></g><g class="chartlet-f chartlet-n-8 chartlet-f-6 chartlet-f-8"><polyline points="128.399,1112.5 230.659,1112.5 222.659,1166.5 136.399,1166.5 128.399,1112.5" class="chartlet-diagram-shadow"/><polyline points="128.399,1110 230.659,1110 222.659,1164 136.399,1164 128.399,1110" class="chartlet-flow-node chartlet-role-teal"><title>Backup – second site</title></polyline><text x="179.529" y="1134.5" text-anchor="middle" class="chartlet-flow-label">Backup</text><text x="179.529" y="1148.5" text-anchor="middle" class="chartlet-flow-sublabel">second site</text></g><g class="chartlet-f chartlet-n-9 chartlet-f-5 chartlet-f-9"><rect x="261.201" y="151.088" width="102.32" height="66" class="chartlet-diagram-shadow"/><rect x="261.201" y="148.588" width="102.32" height="66" class="chartlet-flow-node chartlet-flow-external chartlet-role-gray"><title>School records – legacy system</title></rect><text x="312.361" y="171.088" text-anchor="middle" class="chartlet-flow-label">School</text><text x="312.361" y="187.088" text-anchor="middle" class="chartlet-flow-label">records</text><text x="312.361" y="201.088" text-anchor="middle" class="chartlet-flow-sublabel">legacy system</text></g><g class="chartlet-f chartlet-n-10 chartlet-f-5 chartlet-f-10"><rect x="352.129" y="1121.5" width="98.75" height="36" class="chartlet-diagram-shadow"/><rect x="352.129" y="1119" width="98.75" height="36" class="chartlet-flow-node chartlet-flow-external chartlet-role-gray"><title>SIEM / SOC</title></rect><text x="401.504" y="1141.5" text-anchor="middle" class="chartlet-flow-label">SIEM / SOC</text></g></svg><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-0" for="chartlet-993d7890224c2061-focus-0"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-1" for="chartlet-993d7890224c2061-focus-1"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-2" for="chartlet-993d7890224c2061-focus-2"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-3" for="chartlet-993d7890224c2061-focus-3"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-4" for="chartlet-993d7890224c2061-focus-4"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-5" for="chartlet-993d7890224c2061-focus-5"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-6" for="chartlet-993d7890224c2061-focus-6"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-7" for="chartlet-993d7890224c2061-focus-7"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-8" for="chartlet-993d7890224c2061-focus-8"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-9" for="chartlet-993d7890224c2061-focus-9"></label><label class="chartlet-hotspot" id="chartlet-993d7890224c2061-m-hs-10" for="chartlet-993d7890224c2061-focus-10"></label></div></div><p class="chartlet-source">Source: Illustrative reference architecture</p><details class="chartlet-data" data-viz-text><summary>Show chart data</summary><table><caption>Data for Multi-tenant line-of-business application</caption><thead><tr><th scope="col">Component</th><th scope="col">Kind</th><th scope="col">Boundary</th><th scope="col">Connects to</th></tr></thead><tbody><tr><th scope="row">Teacher, parent</th><td>person</td><td></td><td>Browser (uses)</td></tr><tr><th scope="row">Browser</th><td>frontend</td><td></td><td>Reverse proxy (calls, via HTTPS)</td></tr><tr><th scope="row">School records</th><td>external system</td><td></td><td>Domain API (master data, via REST/JSON)</td></tr><tr><th scope="row">Reverse proxy</th><td>security</td><td>Data center</td><td>Web / BFF (forwards)</td></tr><tr><th scope="row">Web / BFF</th><td>service</td><td>Data center › Application network</td><td>Sign-in (signs in, via OIDC), Domain API (queries, via user context)</td></tr><tr><th scope="row">Sign-in</th><td>security</td><td>Data center › Application network</td><td></td></tr><tr><th scope="row">Domain API</th><td>service</td><td>Data center › Application network</td><td>Domain data (reads, writes, via SQL/TLS), Audit log (logs), SIEM / SOC (events, via Syslog)</td></tr><tr><th scope="row">Domain data</th><td>database</td><td>Data center › Application network › Data zone</td><td>Backup (backs up)</td></tr><tr><th scope="row">Audit log</th><td>database</td><td>Data center › Application network › Data zone</td><td></td></tr><tr><th scope="row">Backup</th><td>storage</td><td></td><td></td></tr><tr><th scope="row">SIEM / SOC</th><td>external system</td><td></td><td></td></tr></tbody></table></details></figure></div>