<mxfile host="app.diagrams.net" modified="2026-04-17T12:00:00.000Z" agent="Claude" version="24.7.17">
  <diagram id="c4-component-backend" name="C4 Component - API Backend">
    <mxGraphModel dx="1400" dy="900" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1600" pageHeight="1100" math="0" shadow="0">
      <root>
        <mxCell id="0"/>
        <mxCell id="1" parent="0"/>

        <mxCell id="title" value="Component Diagram — API Backend" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;fontSize=20;fontStyle=1;fontColor=#1F2937;" vertex="1" parent="1">
          <mxGeometry x="380" y="20" width="740" height="40" as="geometry"/>
        </mxCell>
        <mxCell id="subtitle" value="[C4 Level 3 — Component | Container: API Backend (FastAPI + Python 3.11)]" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;fontSize=12;fontStyle=2;fontColor=#6B7280;" vertex="1" parent="1">
          <mxGeometry x="200" y="55" width="1100" height="25" as="geometry"/>
        </mxCell>

        <!-- Frontend SPA (caller) -->
        <mxCell id="spa" value="&lt;b&gt;Frontend SPA&lt;/b&gt;&lt;br&gt;[Container]&lt;br&gt;&lt;br&gt;React 19, nginx proxy.&lt;br&gt;Calls /api/* routes." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#999999;fontColor=#ffffff;strokeColor=#8C8C8C;arcSize=5;fontSize=10;align=center;" vertex="1" parent="1">
          <mxGeometry x="680" y="90" width="200" height="120" as="geometry"/>
        </mxCell>

        <!-- Container boundary -->
        <mxCell id="be_boundary" value="API Backend [Container: FastAPI + Python 3.11 + Uvicorn]" style="swimlane;fontStyle=1;fillColor=none;strokeColor=#438DD5;startSize=32;rounded=1;arcSize=3;fontSize=12;fontColor=#438DD5;strokeWidth=2;dashed=1;dashPattern=8 4;" vertex="1" parent="1">
          <mxGeometry x="50" y="270" width="1480" height="620" as="geometry"/>
        </mxCell>

        <!-- FastAPI App (router layer) -->
        <mxCell id="comp_app" value="&lt;b&gt;FastAPI App&lt;/b&gt;&lt;br&gt;[Component: FastAPI]&lt;br&gt;&lt;br&gt;ASGI entry point.&lt;br&gt;All routers, CORS, rate limiting." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#85BBF0;fontColor=#23445D;strokeColor=#6196CA;arcSize=5;fontSize=10;align=center;" vertex="1" parent="be_boundary">
          <mxGeometry x="560" y="60" width="260" height="115" as="geometry"/>
        </mxCell>

        <!-- ContactRouter -->
        <mxCell id="comp_contact" value="&lt;b&gt;ContactRouter&lt;/b&gt;&lt;br&gt;[Component: APIRouter]&lt;br&gt;&lt;br&gt;POST /api/contact.&lt;br&gt;Validates and calls EmailService." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#85BBF0;fontColor=#23445D;strokeColor=#6196CA;arcSize=5;fontSize=10;align=center;" vertex="1" parent="be_boundary">
          <mxGeometry x="40" y="60" width="250" height="115" as="geometry"/>
        </mxCell>

        <!-- CVRouter -->
        <mxCell id="comp_cv" value="&lt;b&gt;CVRouter&lt;/b&gt;&lt;br&gt;[Component: APIRouter]&lt;br&gt;&lt;br&gt;GET /api/download-cv.&lt;br&gt;GET /api/cv/generate (feature-flagged)." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#85BBF0;fontColor=#23445D;strokeColor=#6196CA;arcSize=5;fontSize=10;align=center;" vertex="1" parent="be_boundary">
          <mxGeometry x="300" y="60" width="250" height="115" as="geometry"/>
        </mxCell>

        <!-- ProjectsRouter -->
        <mxCell id="comp_projects" value="&lt;b&gt;ProjectsRouter&lt;/b&gt;&lt;br&gt;[Component: APIRouter]&lt;br&gt;&lt;br&gt;GET /api/projects, /experience, /skills.&lt;br&gt;Reads from PostgreSQL DB." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#85BBF0;fontColor=#23445D;strokeColor=#6196CA;arcSize=5;fontSize=10;align=center;" vertex="1" parent="be_boundary">
          <mxGeometry x="830" y="60" width="260" height="115" as="geometry"/>
        </mxCell>

        <!-- AdminRouter -->
        <mxCell id="comp_admin" value="&lt;b&gt;AdminRouter&lt;/b&gt;&lt;br&gt;[Component: APIRouter]&lt;br&gt;&lt;br&gt;POST /api/admin/*.&lt;br&gt;Bearer token auth, DB writes." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#85BBF0;fontColor=#23445D;strokeColor=#6196CA;arcSize=5;fontSize=10;align=center;" vertex="1" parent="be_boundary">
          <mxGeometry x="1100" y="60" width="250" height="115" as="geometry"/>
        </mxCell>

        <!-- HealthRouter -->
        <mxCell id="comp_health" value="&lt;b&gt;HealthRouter&lt;/b&gt;&lt;br&gt;[Component: APIRouter]&lt;br&gt;&lt;br&gt;GET /health (probe).&lt;br&gt;GET /api/health (public)." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#85BBF0;fontColor=#23445D;strokeColor=#6196CA;arcSize=5;fontSize=10;align=center;" vertex="1" parent="be_boundary">
          <mxGeometry x="40" y="290" width="250" height="110" as="geometry"/>
        </mxCell>

        <!-- EmailService -->
        <mxCell id="comp_email" value="&lt;b&gt;EmailService&lt;/b&gt;&lt;br&gt;[Component: smtplib]&lt;br&gt;&lt;br&gt;Notification + confirmation emails.&lt;br&gt;Gmail SMTP:587 TLS." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#85BBF0;fontColor=#23445D;strokeColor=#6196CA;arcSize=5;fontSize=10;align=center;" vertex="1" parent="be_boundary">
          <mxGeometry x="300" y="290" width="260" height="110" as="geometry"/>
        </mxCell>

        <!-- Settings -->
        <mxCell id="comp_settings" value="&lt;b&gt;Settings&lt;/b&gt;&lt;br&gt;[Component: pydantic-settings]&lt;br&gt;&lt;br&gt;EMAIL, DATABASE_URL, MI flag.&lt;br&gt;Reads env vars / Key Vault." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#85BBF0;fontColor=#23445D;strokeColor=#6196CA;arcSize=5;fontSize=10;align=center;" vertex="1" parent="be_boundary">
          <mxGeometry x="570" y="290" width="260" height="110" as="geometry"/>
        </mxCell>

        <!-- Database Layer -->
        <mxCell id="comp_db" value="&lt;b&gt;Database Layer&lt;/b&gt;&lt;br&gt;[Component: SQLAlchemy async]&lt;br&gt;&lt;br&gt;Async engine, ORM models.&lt;br&gt;Alembic migrations, MI token." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#85BBF0;fontColor=#23445D;strokeColor=#6196CA;arcSize=5;fontSize=10;align=center;" vertex="1" parent="be_boundary">
          <mxGeometry x="840" y="290" width="280" height="110" as="geometry"/>
        </mxCell>

        <!-- ManagedIdentity -->
        <mxCell id="comp_mi" value="&lt;b&gt;Managed Identity Auth&lt;/b&gt;&lt;br&gt;[Component: azure-identity]&lt;br&gt;&lt;br&gt;ManagedIdentityCredential.&lt;br&gt;AAD token for PostgreSQL." style="rounded=1;whiteSpace=wrap;html=1;fillColor=#85BBF0;fontColor=#23445D;strokeColor=#6196CA;arcSize=5;fontSize=10;align=center;" vertex="1" parent="be_boundary">
          <mxGeometry x="1130" y="290" width="260" height="110" as="geometry"/>
        </mxCell>

        <!-- External: Gmail SMTP -->
        <mxCell id="ext_gmail" value="&lt;b&gt;Gmail SMTP&lt;/b&gt;&lt;br&gt;[External System]&lt;br&gt;&lt;br&gt;smtp.gmail.com:587 TLS" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#999999;fontColor=#ffffff;strokeColor=#8C8C8C;arcSize=5;fontSize=10;align=center;" vertex="1" parent="1">
          <mxGeometry x="80" y="970" width="200" height="90" as="geometry"/>
        </mxCell>

        <!-- External: PostgreSQL -->
        <mxCell id="ext_psql" value="&lt;b&gt;PostgreSQL Flexible Server&lt;/b&gt;&lt;br&gt;[Container]&lt;br&gt;&lt;br&gt;AAD-only auth, asyncpg" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#999999;fontColor=#ffffff;strokeColor=#8C8C8C;arcSize=5;fontSize=10;align=center;" vertex="1" parent="1">
          <mxGeometry x="860" y="970" width="220" height="90" as="geometry"/>
        </mxCell>

        <!-- External: Azure Entra (MI) -->
        <mxCell id="ext_entra" value="&lt;b&gt;Microsoft Entra ID&lt;/b&gt;&lt;br&gt;[External System]&lt;br&gt;&lt;br&gt;Issues AAD token for MI" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#999999;fontColor=#ffffff;strokeColor=#8C8C8C;arcSize=5;fontSize=10;align=center;" vertex="1" parent="1">
          <mxGeometry x="1210" y="970" width="200" height="90" as="geometry"/>
        </mxCell>

        <!-- Relationships -->
        <!-- SPA → FastAPI App -->
        <mxCell id="e1" value="HTTP /api/*" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="spa" target="comp_app" parent="1">
          <mxGeometry relative="1" as="geometry">
            <Array as="points">
              <mxPoint x="780" y="250"/>
              <mxPoint x="690" y="250"/>
            </Array>
          </mxGeometry>
        </mxCell>
        <!-- App → ContactRouter -->
        <mxCell id="e2" value="Routes" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_app" target="comp_contact" parent="be_boundary">
          <mxGeometry relative="1" as="geometry">
            <Array as="points">
              <mxPoint x="560" y="117"/>
              <mxPoint x="290" y="117"/>
            </Array>
          </mxGeometry>
        </mxCell>
        <!-- App → CVRouter -->
        <mxCell id="e3" value="Routes" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_app" target="comp_cv" parent="be_boundary">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <!-- App → ProjectsRouter -->
        <mxCell id="e4" value="Routes" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_app" target="comp_projects" parent="be_boundary">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <!-- App → AdminRouter -->
        <mxCell id="e5" value="Routes" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_app" target="comp_admin" parent="be_boundary">
          <mxGeometry relative="1" as="geometry">
            <Array as="points">
              <mxPoint x="820" y="117"/>
              <mxPoint x="1100" y="117"/>
            </Array>
          </mxGeometry>
        </mxCell>
        <!-- ContactRouter → EmailService -->
        <mxCell id="e6" value="Calls" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_contact" target="comp_email" parent="be_boundary">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <!-- EmailService → Settings -->
        <mxCell id="e7" value="Reads" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_email" target="comp_settings" parent="be_boundary">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <!-- ProjectsRouter → DB -->
        <mxCell id="e8" value="Queries" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_projects" target="comp_db" parent="be_boundary">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <!-- AdminRouter → DB -->
        <mxCell id="e9" value="Writes" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_admin" target="comp_db" parent="be_boundary">
          <mxGeometry relative="1" as="geometry">
            <Array as="points">
              <mxPoint x="1225" y="205"/>
              <mxPoint x="980" y="205"/>
            </Array>
          </mxGeometry>
        </mxCell>
        <!-- DB → ManagedIdentity -->
        <mxCell id="e10" value="Gets token" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_db" target="comp_mi" parent="be_boundary">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <!-- EmailService → Gmail (external) -->
        <mxCell id="e11" value="SMTP:587" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_email" target="ext_gmail" parent="1">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <!-- DB → PostgreSQL (external) -->
        <mxCell id="e12" value="asyncpg" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_db" target="ext_psql" parent="1">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <!-- ManagedIdentity → Entra (external) -->
        <mxCell id="e13" value="AAD token" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#707070;strokeWidth=1.5;fontSize=9;" edge="1" source="comp_mi" target="ext_entra" parent="1">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>

        <!-- Legend -->
        <mxCell id="legend_bg" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F9FAFB;strokeColor=#D1D5DB;arcSize=5;" vertex="1" parent="1">
          <mxGeometry x="30" y="90" width="310" height="145" as="geometry"/>
        </mxCell>
        <mxCell id="leg_title" value="Legend" style="text;html=1;strokeColor=none;fillColor=none;fontSize=11;fontStyle=1;fontColor=#374151;" vertex="1" parent="1">
          <mxGeometry x="45" y="98" width="60" height="20" as="geometry"/>
        </mxCell>
        <mxCell id="leg_c" value="" style="rounded=1;fillColor=#85BBF0;strokeColor=#6196CA;" vertex="1" parent="1">
          <mxGeometry x="50" y="124" width="22" height="16" as="geometry"/>
        </mxCell>
        <mxCell id="leg_c_l" value="Component (this container)" style="text;html=1;strokeColor=none;fillColor=none;fontSize=10;" vertex="1" parent="1">
          <mxGeometry x="80" y="124" width="200" height="18" as="geometry"/>
        </mxCell>
        <mxCell id="leg_e" value="" style="rounded=1;fillColor=#999999;strokeColor=#8C8C8C;" vertex="1" parent="1">
          <mxGeometry x="50" y="148" width="22" height="16" as="geometry"/>
        </mxCell>
        <mxCell id="leg_e_l" value="External Container / System" style="text;html=1;strokeColor=none;fillColor=none;fontSize=10;" vertex="1" parent="1">
          <mxGeometry x="80" y="148" width="200" height="18" as="geometry"/>
        </mxCell>
        <mxCell id="leg_b" value="" style="rounded=1;fillColor=none;strokeColor=#438DD5;dashed=1;dashPattern=8 4;strokeWidth=2;" vertex="1" parent="1">
          <mxGeometry x="50" y="172" width="22" height="16" as="geometry"/>
        </mxCell>
        <mxCell id="leg_b_l" value="Container Boundary" style="text;html=1;strokeColor=none;fillColor=none;fontSize=10;" vertex="1" parent="1">
          <mxGeometry x="80" y="172" width="140" height="18" as="geometry"/>
        </mxCell>
        <mxCell id="leg_ext_cont" value="" style="rounded=1;fillColor=#438DD5;strokeColor=#3C7FC0;" vertex="1" parent="1">
          <mxGeometry x="50" y="196" width="22" height="16" as="geometry"/>
        </mxCell>
        <mxCell id="leg_ext_cont_l" value="External Container (other C4 boundary)" style="text;html=1;strokeColor=none;fillColor=none;fontSize=10;" vertex="1" parent="1">
          <mxGeometry x="80" y="196" width="230" height="18" as="geometry"/>
        </mxCell>
      </root>
    </mxGraphModel>
  </diagram>
</mxfile>
