<?xml version="1.0" encoding="UTF-8"?>
<mxfile host="Electron" modified="2026-02-23T08:00:00.000Z" agent="draw.io" version="24.0.0">
  <diagram name="Angular + .NET Integration" id="dotnet-integration">
    <mxGraphModel dx="1400" dy="800" grid="1" gridSize="10">
      <root>
        <mxCell id="0" />
        <mxCell id="1" parent="0" />

        <!-- Title -->
        <mxCell id="title" value="Angular 21 ↔ .NET 10 Integration (Part 4)" style="text;html=1;strokeColor=none;fillColor=none;align=center;fontSize=17;fontStyle=1;" vertex="1" parent="1">
          <mxGeometry x="100" y="20" width="1000" height="40" as="geometry" />
        </mxCell>

        <!-- ANGULAR APP -->
        <mxCell id="ng-bg" value="Angular 21 App" style="swimlane;startSize=30;fillColor=#dae8fc;strokeColor=#6c8ebf;fontStyle=1;fontSize=13;" vertex="1" parent="1">
          <mxGeometry x="60" y="80" width="440" height="540" as="geometry" />
        </mxCell>

        <mxCell id="ng-auth-interceptor" value="&lt;b&gt;authInterceptor&lt;/b&gt;&lt;br/&gt;Attaches Bearer JWT&lt;br/&gt;Handles 401 → refresh" style="rounded=1;fillColor=#E3F2FD;strokeColor=#1565C0;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="ng-bg">
          <mxGeometry x="20" y="50" width="200" height="65" as="geometry" />
        </mxCell>

        <mxCell id="ng-error-interceptor" value="&lt;b&gt;errorInterceptor&lt;/b&gt;&lt;br/&gt;Parses Problem Details&lt;br/&gt;Shows notifications" style="rounded=1;fillColor=#E3F2FD;strokeColor=#1565C0;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="ng-bg">
          <mxGeometry x="230" y="50" width="190" height="65" as="geometry" />
        </mxCell>

        <mxCell id="ng-kiota" value="&lt;b&gt;TechShopApiClient&lt;/b&gt;&lt;br/&gt;Kiota-generated TypeScript client&lt;br/&gt;Fully typed from OpenAPI 3.1" style="rounded=1;fillColor=#E8F5E9;strokeColor=#2E7D32;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="ng-bg">
          <mxGeometry x="80" y="155" width="280" height="65" as="geometry" />
        </mxCell>

        <mxCell id="ng-auth-service" value="&lt;b&gt;AuthService&lt;/b&gt;&lt;br/&gt;Signal-based JWT store&lt;br/&gt;isAuthenticated() · accessToken()" style="rounded=1;fillColor=#F3E5F5;strokeColor=#7B1FA2;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="ng-bg">
          <mxGeometry x="80" y="255" width="280" height="65" as="geometry" />
        </mxCell>

        <mxCell id="ng-signalr" value="&lt;b&gt;InventoryRealtimeService&lt;/b&gt;&lt;br/&gt;@microsoft/signalr&lt;br/&gt;Converts to Signal via toSignal()" style="rounded=1;fillColor=#FFF3E0;strokeColor=#E65100;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="ng-bg">
          <mxGeometry x="80" y="355" width="280" height="65" as="geometry" />
        </mxCell>

        <mxCell id="ng-proxy" value="&lt;b&gt;Dev Proxy (proxy.conf.json)&lt;/b&gt;&lt;br/&gt;/api → localhost:5000&lt;br/&gt;/hubs → localhost:5000 (ws)" style="rounded=1;fillColor=#F5F5F5;strokeColor=#757575;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="ng-bg">
          <mxGeometry x="80" y="455" width="280" height="60" as="geometry" />
        </mxCell>

        <!-- DOTNET API -->
        <mxCell id="dn-bg" value=".NET 10 Minimal API" style="swimlane;startSize=30;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;fontSize=13;" vertex="1" parent="1">
          <mxGeometry x="680" y="80" width="440" height="540" as="geometry" />
        </mxCell>

        <mxCell id="dn-openapi" value="&lt;b&gt;OpenAPI 3.1 (Built-in)&lt;/b&gt;&lt;br/&gt;MapOpenApi() — no Swashbuckle&lt;br/&gt;Served at /openapi/v1.json" style="rounded=1;fillColor=#F1F8E9;strokeColor=#558B2F;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="dn-bg">
          <mxGeometry x="100" y="50" width="240" height="65" as="geometry" />
        </mxCell>

        <mxCell id="dn-jwt" value="&lt;b&gt;JWT Auth (.NET Identity)&lt;/b&gt;&lt;br/&gt;/api/auth/token → AccessToken&lt;br/&gt;/api/auth/refresh → New tokens" style="rounded=1;fillColor=#F1F8E9;strokeColor=#558B2F;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="dn-bg">
          <mxGeometry x="100" y="155" width="240" height="65" as="geometry" />
        </mxCell>

        <mxCell id="dn-problem" value="&lt;b&gt;Problem Details RFC 9457&lt;/b&gt;&lt;br/&gt;{ status, title, detail, errors }&lt;br/&gt;All error responses standardised" style="rounded=1;fillColor=#F1F8E9;strokeColor=#558B2F;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="dn-bg">
          <mxGeometry x="100" y="255" width="240" height="65" as="geometry" />
        </mxCell>

        <mxCell id="dn-signalr" value="&lt;b&gt;InventoryHub (SignalR)&lt;/b&gt;&lt;br/&gt;Groups by productId&lt;br/&gt;Pushes InventoryUpdated events" style="rounded=1;fillColor=#FFF3E0;strokeColor=#E65100;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="dn-bg">
          <mxGeometry x="100" y="355" width="240" height="65" as="geometry" />
        </mxCell>

        <mxCell id="dn-cors" value="&lt;b&gt;CORS Policy&lt;/b&gt;&lt;br/&gt;AllowCredentials for SignalR&lt;br/&gt;Whitelist Angular origins" style="rounded=1;fillColor=#F5F5F5;strokeColor=#757575;fontSize=11;whiteSpace=wrap;html=1;" vertex="1" parent="dn-bg">
          <mxGeometry x="100" y="455" width="240" height="60" as="geometry" />
        </mxCell>

        <!-- KIOTA CODEGEN (central) -->
        <mxCell id="kiota-center" value="&lt;b&gt;Kiota Codegen&lt;/b&gt;&lt;br/&gt;kiota generate --openapi /openapi/v1.json&lt;br/&gt;CI checks for drift on every PR" style="rounded=1;fillColor=#FFF9C4;strokeColor=#F57F17;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="490" y="200" width="220" height="70" as="geometry" />
        </mxCell>

        <!-- Arrows -->
        <mxCell id="a-openapi" edge="1" source="dn-openapi" target="kiota-center" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#558B2F;strokeWidth=2;" parent="1"><mxGeometry relative="1" as="geometry"/></mxCell>
        <mxCell id="a-kiota-ng" edge="1" source="kiota-center" target="ng-kiota" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#1565C0;strokeWidth=2;" parent="1"><mxGeometry relative="1" as="geometry"/></mxCell>

        <mxCell id="a-http" edge="1" source="ng-kiota" target="dn-jwt" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#333;strokeWidth=2;dashed=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" parent="1"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="580" y="455"/><mxPoint x="580" y="285"/></Array></mxGeometry></mxCell>

        <mxCell id="a-ws" edge="1" source="ng-signalr" target="dn-signalr" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#E65100;strokeWidth=2;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" parent="1"><mxGeometry relative="1" as="geometry"><mxPoint x="580" y="575"/></mxGeometry></mxCell>

        <!-- Labels on arrows -->
        <mxCell id="lbl-http" value="HTTP/JSON" style="text;html=1;fontSize=10;fillColor=#ffffcc;strokeColor=#999;" vertex="1" parent="1">
          <mxGeometry x="490" y="440" width="80" height="20" as="geometry" />
        </mxCell>
        <mxCell id="lbl-ws" value="WebSocket" style="text;html=1;fontSize=10;fillColor=#FFE0B2;strokeColor=#E65100;" vertex="1" parent="1">
          <mxGeometry x="490" y="555" width="80" height="20" as="geometry" />
        </mxCell>

      </root>
    </mxGraphModel>
  </diagram>
</mxfile>
