nordabiz/docs/architecture/diagrams/system-architecture.drawio

411 lines
36 KiB
Plaintext

<mxfile host="draw.io" modified="2026-02-12" agent="Claude Code" type="device">
<diagram id="nordabiz-system-arch" name="Architektura Systemu">
<mxGraphModel dx="1800" dy="1200" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="2200" pageHeight="1500" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<!-- ==================== TYTUŁ ==================== -->
<mxCell id="title" value="NordaBiz — Architektura Systemu" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=22;fontStyle=1;fontColor=#1a1a2e;" vertex="1" parent="1">
<mxGeometry x="700" y="10" width="420" height="40" as="geometry"/>
</mxCell>
<mxCell id="subtitle" value="nordabiznes.pl &amp;nbsp;|&amp;nbsp; Platforma katalogowa Norda Biznes &amp;nbsp;|&amp;nbsp; luty 2026" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=11;fontColor=#666666;" vertex="1" parent="1">
<mxGeometry x="680" y="46" width="460" height="24" as="geometry"/>
</mxCell>
<!-- ==================== INTERNET ==================== -->
<mxCell id="zone_internet_label" value="INTERNET" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;fontStyle=1;fontColor=#999999;" vertex="1" parent="1">
<mxGeometry x="40" y="78" width="70" height="20" as="geometry"/>
</mxCell>
<mxCell id="users" value="&lt;b&gt;Użytkownicy&lt;/b&gt;&lt;br&gt;(przeglądarki)" style="shape=mxgraph.cisco.people.standing_man;sketch=0;html=1;fillColor=#e6d0de;strokeColor=#AE4132;fontColor=#333333;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="400" y="80" width="50" height="55" as="geometry"/>
</mxCell>
<mxCell id="admin" value="&lt;b&gt;Administrator&lt;/b&gt;&lt;br&gt;(SSH / HTTPS)" style="shape=mxgraph.cisco.people.standing_man;sketch=0;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontColor=#333333;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="580" y="80" width="50" height="55" as="geometry"/>
</mxCell>
<mxCell id="dns" value="&lt;b&gt;DNS&lt;/b&gt;&lt;br&gt;OVH.com" style="ellipse;shape=cloud;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="210" y="82" width="110" height="55" as="geometry"/>
</mxCell>
<!-- ==================== STREFA DMZ ==================== -->
<mxCell id="zone_dmz" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;dashed=1;strokeWidth=2;opacity=30;" vertex="1" parent="1">
<mxGeometry x="150" y="170" width="780" height="120" as="geometry"/>
</mxCell>
<mxCell id="zone_dmz_label" value="STREFA DMZ (sieć obwodowa)" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;fontStyle=1;fontColor=#b8860b;" vertex="1" parent="1">
<mxGeometry x="160" y="173" width="200" height="20" as="geometry"/>
</mxCell>
<mxCell id="fortigate" value="&lt;b&gt;FortiGate-500D&lt;/b&gt;&lt;br&gt;Zapora sieciowa / NAT&lt;br&gt;&lt;font style=&quot;font-size:9px;color:#888&quot;&gt;85.237.177.83&lt;/font&gt;" style="shape=mxgraph.cisco.firewalls.firewall;sketch=0;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontColor=#333333;fontSize=10;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;" vertex="1" parent="1">
<mxGeometry x="220" y="190" width="50" height="50" as="geometry"/>
</mxCell>
<mxCell id="npm" value="&lt;b&gt;Serwer Proxy (NPM)&lt;/b&gt;&lt;br&gt;R11-REVPROXY-01 (VM 119)&lt;br&gt;&lt;font style=&quot;font-size:9px;color:#888&quot;&gt;10.22.68.250 | SSL Let's Encrypt&lt;br&gt;Proxy Host #27 (prod) | #44 (staging)&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontColor=#333333;fontSize=11;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="600" y="190" width="260" height="80" as="geometry"/>
</mxCell>
<!-- ==================== PRODUKCJA ==================== -->
<mxCell id="zone_prod" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;dashed=1;strokeWidth=2;opacity=30;" vertex="1" parent="1">
<mxGeometry x="40" y="320" width="1270" height="560" as="geometry"/>
</mxCell>
<mxCell id="zone_prod_label" value="PRODUKCJA &amp;nbsp;|&amp;nbsp; NORDABIZ-01 (VM 249) &amp;nbsp;|&amp;nbsp; 10.22.68.249 &amp;nbsp;|&amp;nbsp; nordabiznes.pl" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=11;fontStyle=1;fontColor=#4472c4;" vertex="1" parent="1">
<mxGeometry x="50" y="323" width="500" height="20" as="geometry"/>
</mxCell>
<!-- Flask Container -->
<mxCell id="flask" value="&lt;b style=&quot;font-size:14px&quot;&gt;Flask 3.0 + Gunicorn&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:9px;color:#555&quot;&gt;Port 5000 | 4 workery | www-data | Python 3.9+&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontColor=#333333;fontSize=11;verticalAlign=top;spacingTop=8;" vertex="1" parent="1">
<mxGeometry x="60" y="355" width="710" height="505" as="geometry"/>
</mxCell>
<!-- === MODUŁY APLIKACJI (Blueprinty) === -->
<mxCell id="bp_header" value="&lt;b&gt;Moduły aplikacji&lt;/b&gt; (17 blueprintów, 375+ tras)" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;fontStyle=0;fontColor=#4472c4;" vertex="1" parent="1">
<mxGeometry x="80" y="395" width="300" height="20" as="geometry"/>
</mxCell>
<mxCell id="bp_katalog" value="&lt;b&gt;Katalog firm&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Lista, profile, wyszukiwanie&lt;br&gt;~20 tras&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D4E1F5;strokeColor=#6c8ebf;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="80" y="420" width="155" height="50" as="geometry"/>
</mxCell>
<mxCell id="bp_admin" value="&lt;b&gt;Panel administracyjny&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;~100 tras, 16 plików&lt;br&gt;Firmy, użytkownicy, dane&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D4E1F5;strokeColor=#6c8ebf;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="245" y="420" width="155" height="50" as="geometry"/>
</mxCell>
<mxCell id="bp_forum" value="&lt;b&gt;Forum i społeczność&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Dyskusje, wiadomości&lt;br&gt;~68 tras&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D4E1F5;strokeColor=#6c8ebf;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="410" y="420" width="155" height="50" as="geometry"/>
</mxCell>
<mxCell id="bp_zopk" value="&lt;b&gt;ZOPK&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Baza wiedzy, timeline&lt;br&gt;~55 tras&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D4E1F5;strokeColor=#6c8ebf;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="575" y="420" width="155" height="50" as="geometry"/>
</mxCell>
<mxCell id="bp_chat" value="&lt;b&gt;Czat AI (NordaGPT)&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Asystent AI, 9 tras&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D4E1F5;strokeColor=#6c8ebf;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="80" y="480" width="155" height="45" as="geometry"/>
</mxCell>
<mxCell id="bp_audit" value="&lt;b&gt;Audyt cyfrowy&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;SEO, IT, raporty&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D4E1F5;strokeColor=#6c8ebf;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="245" y="480" width="155" height="45" as="geometry"/>
</mxCell>
<mxCell id="bp_membership" value="&lt;b&gt;Członkostwo&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Składki, korzyści, edukacja&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D4E1F5;strokeColor=#6c8ebf;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="410" y="480" width="155" height="45" as="geometry"/>
</mxCell>
<mxCell id="bp_api" value="&lt;b&gt;API i autoryzacja&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;~73 tras, OAuth&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D4E1F5;strokeColor=#6c8ebf;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="575" y="480" width="155" height="45" as="geometry"/>
</mxCell>
<!-- === USŁUGI WEWNĘTRZNE === -->
<mxCell id="svc_header" value="&lt;b&gt;Usługi wewnętrzne&lt;/b&gt; (27 serwisów)" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;fontStyle=0;fontColor=#9673a6;" vertex="1" parent="1">
<mxGeometry x="80" y="540" width="210" height="20" as="geometry"/>
</mxCell>
<mxCell id="svc_search" value="&lt;b&gt;Wyszukiwarka&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;FTS + fuzzy + synonimy&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="80" y="565" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_gemini" value="&lt;b&gt;GeminiService&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Sztuczna inteligencja&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="235" y="565" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_chat" value="&lt;b&gt;NordaGPT&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Czat AI + kontekst firm&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="390" y="565" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_knowledge" value="&lt;b&gt;Bazy wiedzy&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Norda + ZOPK Knowledge&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="545" y="565" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_seo" value="&lt;b&gt;Audyt SEO&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;PageSpeed + CrUX + INP&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="80" y="617" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_gbp" value="&lt;b&gt;Google Moja Firma&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Places API, opinie&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="235" y="617" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_social" value="&lt;b&gt;Media społecznościowe&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;FB, IG, LI, YT, TikTok&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="390" y="617" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_benchmark" value="&lt;b&gt;Benchmarki&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Średnie per kategoria&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="545" y="617" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_email" value="&lt;b&gt;Poczta e-mail&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;MS Graph OAuth&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="80" y="669" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_krs" value="&lt;b&gt;KRS / CEIDG&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Rejestry firm&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="235" y="669" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_oauth" value="&lt;b&gt;OAuth 2.0&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Google + Meta&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="390" y="669" width="145" height="42" as="geometry"/>
</mxCell>
<mxCell id="svc_other" value="&lt;b&gt;Inne usługi&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Pliki, YouTube, monitoring&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="545" y="669" width="145" height="42" as="geometry"/>
</mxCell>
<!-- Auth/Security -->
<mxCell id="auth" value="&lt;b&gt;Bezpieczeństwo&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Flask-Login | CSRF | Rate Limiter (200/dzień, 50/godz.)&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="80" y="725" width="310" height="40" as="geometry"/>
</mxCell>
<mxCell id="templates" value="&lt;b&gt;Szablony Jinja2&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;HTML5 + CSS3 + Vanilla JS&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D4E1F5;strokeColor=#6c8ebf;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="400" y="725" width="155" height="40" as="geometry"/>
</mxCell>
<mxCell id="sqlalchemy" value="&lt;b&gt;SQLAlchemy 2.0&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;ORM + modele danych&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D4E1F5;strokeColor=#6c8ebf;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="565" y="725" width="155" height="40" as="geometry"/>
</mxCell>
<!-- PostgreSQL PRODUKCJA -->
<mxCell id="postgres" value="&lt;b style=&quot;font-size:13px&quot;&gt;PostgreSQL 14&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:9px;color:#555&quot;&gt;localhost:5432&lt;br&gt;Baza: nordabiz&lt;br&gt;40 tabel | 11 domen&lt;br&gt;pg_trgm + uuid-ossp&lt;/font&gt;" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=12;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#333333;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="800" y="370" width="180" height="120" as="geometry"/>
</mxCell>
<!-- DB Domains -->
<mxCell id="db_domains_label" value="&lt;b&gt;Domeny danych:&lt;/b&gt;" style="text;html=1;align=left;verticalAlign=top;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=9;fontColor=#555;" vertex="1" parent="1">
<mxGeometry x="800" y="500" width="100" height="20" as="geometry"/>
</mxCell>
<mxCell id="db_core" value="&lt;font style=&quot;font-size:8px&quot;&gt;Firmy (9 tabel)&lt;br&gt;Treści (10 tabel)&lt;br&gt;Forum (7 tabel)&lt;br&gt;Czat AI (4 tabele)&lt;br&gt;Audyt (3 tabele)&lt;br&gt;Członkostwo (2)&lt;br&gt;Ogłoszenia (3)&lt;br&gt;Kalendarz (2)&lt;br&gt;+ 3 inne domeny&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#333333;fontSize=9;align=left;spacingLeft=8;" vertex="1" parent="1">
<mxGeometry x="800" y="520" width="180" height="130" as="geometry"/>
</mxCell>
<!-- Zadania automatyczne (Cron) -->
<mxCell id="cron_label" value="&lt;b&gt;Zadania automatyczne&lt;/b&gt;" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;fontStyle=0;fontColor=#7f6000;" vertex="1" parent="1">
<mxGeometry x="800" y="665" width="160" height="20" as="geometry"/>
</mxCell>
<mxCell id="cron_box" value="&lt;font style=&quot;font-size:8px&quot;&gt;&#x23F0; Co godzinę: backup bazy&lt;br&gt;&#x23F0; Co godzinę: ZOPK ekstrakcja&lt;br&gt;&#x1F4C5; Codziennie: pełny backup&lt;br&gt;&#x1F4C5; Codziennie: sync PBS&lt;br&gt;&#x1F4C6; Miesięcznie: aktualizacja stron&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontColor=#333333;fontSize=9;align=left;spacingLeft=8;" vertex="1" parent="1">
<mxGeometry x="800" y="688" width="200" height="80" as="geometry"/>
</mxCell>
<!-- ==================== ZEWNĘTRZNE API ==================== -->
<mxCell id="zone_api" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;dashed=1;strokeWidth=1;opacity=40;" vertex="1" parent="1">
<mxGeometry x="1050" y="320" width="250" height="440" as="geometry"/>
</mxCell>
<mxCell id="zone_api_label" value="ZEWNĘTRZNE API" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;fontStyle=1;fontColor=#999999;" vertex="1" parent="1">
<mxGeometry x="1060" y="323" width="120" height="20" as="geometry"/>
</mxCell>
<mxCell id="api_gemini" value="&lt;b&gt;Google Gemini AI&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;gemini-3-flash (sztuczna inteligencja)&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff;strokeColor=#4285F4;fontColor=#333333;fontSize=10;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="1070" y="350" width="210" height="38" as="geometry"/>
</mxCell>
<mxCell id="api_pagespeed" value="&lt;b&gt;Google PageSpeed&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Core Web Vitals + CrUX&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff;strokeColor=#4285F4;fontColor=#333333;fontSize=10;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="1070" y="398" width="210" height="38" as="geometry"/>
</mxCell>
<mxCell id="api_places" value="&lt;b&gt;Google Places API&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Google Moja Firma, opinie&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff;strokeColor=#4285F4;fontColor=#333333;fontSize=10;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="1070" y="446" width="210" height="38" as="geometry"/>
</mxCell>
<mxCell id="api_oauth" value="&lt;b&gt;Google OAuth 2.0&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;GBP + Search Console&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff;strokeColor=#34A853;fontColor=#333333;fontSize=10;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="1070" y="494" width="210" height="38" as="geometry"/>
</mxCell>
<mxCell id="api_brave" value="&lt;b&gt;Brave Search API&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Wiadomości + social media&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff;strokeColor=#FB542B;fontColor=#333333;fontSize=10;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="1070" y="542" width="210" height="38" as="geometry"/>
</mxCell>
<mxCell id="api_krs" value="&lt;b&gt;KRS / CEIDG API&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Publiczne rejestry firm&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff;strokeColor=#333333;fontColor=#333333;fontSize=10;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="1070" y="590" width="210" height="38" as="geometry"/>
</mxCell>
<mxCell id="api_msgraph" value="&lt;b&gt;Microsoft Graph&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Poczta e-mail (OAuth 2.0)&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff;strokeColor=#00A4EF;fontColor=#333333;fontSize=10;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="1070" y="638" width="210" height="38" as="geometry"/>
</mxCell>
<mxCell id="api_youtube" value="&lt;b&gt;YouTube Data API v3&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;Statystyki kanałów&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff;strokeColor=#FF0000;fontColor=#333333;fontSize=10;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="1070" y="686" width="210" height="38" as="geometry"/>
</mxCell>
<!-- ==================== STAGING ==================== -->
<mxCell id="zone_staging" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFF8E1;strokeColor=#FF8F00;dashed=1;strokeWidth=2;opacity=40;" vertex="1" parent="1">
<mxGeometry x="40" y="910" width="540" height="150" as="geometry"/>
</mxCell>
<mxCell id="zone_staging_label" value="ŚRODOWISKO TESTOWE (STAGING) &amp;nbsp;|&amp;nbsp; VM 248 &amp;nbsp;|&amp;nbsp; 10.22.68.248 &amp;nbsp;|&amp;nbsp; staging.nordabiznes.pl" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;fontStyle=1;fontColor=#FF8F00;" vertex="1" parent="1">
<mxGeometry x="50" y="913" width="520" height="20" as="geometry"/>
</mxCell>
<mxCell id="staging_flask" value="&lt;b&gt;Flask + Gunicorn&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px;color:#555&quot;&gt;Kopia produkcji&lt;br&gt;Port 5000&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFF8E1;strokeColor=#FF8F00;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="60" y="940" width="200" height="55" as="geometry"/>
</mxCell>
<mxCell id="staging_pg" value="&lt;b&gt;PostgreSQL&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px;color:#555&quot;&gt;nordabiz_staging&lt;br&gt;localhost:5432&lt;/font&gt;" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=8;fillColor=#FFF8E1;strokeColor=#FF8F00;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="290" y="938" width="130" height="60" as="geometry"/>
</mxCell>
<mxCell id="staging_note" value="&lt;font style=&quot;font-size:8px;color:#888&quot;&gt;Obowiązkowy test przed&lt;br&gt;wdrożeniem na produkcję!&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="440" y="950" width="130" height="40" as="geometry"/>
</mxCell>
<!-- Staging connection -->
<mxCell id="conn_staging_internal" style="rounded=1;strokeColor=#FF8F00;strokeWidth=1;" edge="1" source="staging_flask" target="staging_pg" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- ==================== STACJA DEWELOPERSKA ==================== -->
<mxCell id="zone_dev" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#E8F5E9;strokeColor=#4CAF50;dashed=1;strokeWidth=2;opacity=40;" vertex="1" parent="1">
<mxGeometry x="620" y="910" width="500" height="150" as="geometry"/>
</mxCell>
<mxCell id="zone_dev_label" value="STACJA DEWELOPERSKA &amp;nbsp;|&amp;nbsp; macOS &amp;nbsp;|&amp;nbsp; localhost" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;fontStyle=1;fontColor=#4CAF50;" vertex="1" parent="1">
<mxGeometry x="630" y="913" width="340" height="20" as="geometry"/>
</mxCell>
<mxCell id="dev_flask" value="&lt;b&gt;Flask dev server&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px;color:#555&quot;&gt;python3 app.py&lt;br&gt;Port 5000 / 5001&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#E8F5E9;strokeColor=#4CAF50;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="640" y="940" width="160" height="55" as="geometry"/>
</mxCell>
<mxCell id="dev_docker" value="&lt;b&gt;Docker PostgreSQL&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px;color:#555&quot;&gt;postgres:16&lt;br&gt;localhost:5433&lt;/font&gt;" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=8;fillColor=#E8F5E9;strokeColor=#4CAF50;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="830" y="938" width="130" height="60" as="geometry"/>
</mxCell>
<mxCell id="dev_tools" value="&lt;font style=&quot;font-size:8px;color:#555&quot;&gt;VS Code + Claude Code&lt;br&gt;pytest | Docker Compose&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="980" y="950" width="130" height="40" as="geometry"/>
</mxCell>
<!-- Dev connection -->
<mxCell id="conn_dev_internal" style="rounded=1;strokeColor=#4CAF50;strokeWidth=1;" edge="1" source="dev_flask" target="dev_docker" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- ==================== REPOZYTORIA KODU ==================== -->
<mxCell id="zone_git" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ECEFF1;strokeColor=#78909C;dashed=1;strokeWidth=1;opacity=40;" vertex="1" parent="1">
<mxGeometry x="40" y="1090" width="1080" height="100" as="geometry"/>
</mxCell>
<mxCell id="zone_git_label" value="REPOZYTORIA KODU I WDROŻENIE" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;fontStyle=1;fontColor=#78909C;" vertex="1" parent="1">
<mxGeometry x="50" y="1093" width="220" height="20" as="geometry"/>
</mxCell>
<mxCell id="git_github" value="&lt;b&gt;GitHub&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;pienczyn/nordabiz&lt;br&gt;Backup w chmurze + CI/CD&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ECEFF1;strokeColor=#78909C;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="60" y="1120" width="180" height="50" as="geometry"/>
</mxCell>
<mxCell id="git_gitea" value="&lt;b&gt;Gitea (INPI)&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:8px&quot;&gt;10.22.68.180&lt;br&gt;Repozytorium wewnętrzne&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ECEFF1;strokeColor=#78909C;fontColor=#333333;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="270" y="1120" width="180" height="50" as="geometry"/>
</mxCell>
<!-- Deployment flow -->
<mxCell id="deploy_flow" value="&lt;b&gt;Przepływ wdrożenia:&lt;/b&gt;&lt;br&gt;&lt;font style=&quot;font-size:9px&quot;&gt;1. git push (origin + inpi) → 2. Wdrożenie na staging → 3. Test manualny → 4. git pull na produkcji → 5. Migracje SQL → 6. Restart serwisu&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#E3F2FD;strokeColor=#1565C0;fontColor=#333333;fontSize=10;align=left;spacingLeft=10;" vertex="1" parent="1">
<mxGeometry x="480" y="1115" width="620" height="55" as="geometry"/>
</mxCell>
<!-- ==================== POŁĄCZENIA ==================== -->
<!-- Users → DNS -->
<mxCell id="conn_user_dns" style="edgeStyle=orthogonalEdgeStyle;rounded=1;strokeColor=#666666;strokeWidth=1;fontSize=9;fontColor=#888;" edge="1" source="users" target="dns" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- Users → FortiGate -->
<mxCell id="conn_user_fw" value="HTTPS :443" style="edgeStyle=orthogonalEdgeStyle;rounded=1;strokeColor=#b85450;strokeWidth=2;fontSize=9;fontColor=#b85450;" edge="1" source="users" target="fortigate" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- Admin → NPM -->
<mxCell id="conn_admin_npm" value="SSH + HTTPS" style="edgeStyle=orthogonalEdgeStyle;rounded=1;strokeColor=#d6b656;strokeWidth=1;fontSize=9;fontColor=#888;dashed=1;" edge="1" source="admin" target="npm" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- FortiGate → NPM -->
<mxCell id="conn_fw_npm" value="NAT → :443" style="edgeStyle=orthogonalEdgeStyle;rounded=1;strokeColor=#b85450;strokeWidth=2;fontSize=9;fontColor=#b85450;" edge="1" source="fortigate" target="npm" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- NPM → Flask PROD -->
<mxCell id="conn_npm_flask" value="HTTP :5000" style="edgeStyle=orthogonalEdgeStyle;rounded=1;strokeColor=#6c8ebf;strokeWidth=2;fontSize=9;fontColor=#6c8ebf;" edge="1" source="npm" target="flask" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- NPM → Flask STAGING -->
<mxCell id="conn_npm_staging" value="HTTP :5000" style="edgeStyle=orthogonalEdgeStyle;rounded=1;strokeColor=#FF8F00;strokeWidth=1;fontSize=9;fontColor=#FF8F00;dashed=1;" edge="1" source="npm" target="staging_flask" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- Flask → PostgreSQL -->
<mxCell id="conn_flask_pg" value="SQL :5432" style="edgeStyle=orthogonalEdgeStyle;rounded=1;strokeColor=#82b366;strokeWidth=2;fontSize=9;fontColor=#82b366;" edge="1" source="flask" target="postgres" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- Service → API connections -->
<mxCell id="conn_gemini" style="rounded=1;strokeColor=#4285F4;strokeWidth=1;dashed=1;" edge="1" source="svc_gemini" target="api_gemini" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="conn_seo_ps" style="rounded=1;strokeColor=#4285F4;strokeWidth=1;dashed=1;" edge="1" source="svc_seo" target="api_pagespeed" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="conn_gbp_places" style="rounded=1;strokeColor=#4285F4;strokeWidth=1;dashed=1;" edge="1" source="svc_gbp" target="api_places" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="conn_social_brave" style="rounded=1;strokeColor=#FB542B;strokeWidth=1;dashed=1;" edge="1" source="svc_social" target="api_brave" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="conn_krs_api" style="rounded=1;strokeColor=#333333;strokeWidth=1;dashed=1;" edge="1" source="svc_krs" target="api_krs" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="conn_email_ms" style="rounded=1;strokeColor=#00A4EF;strokeWidth=1;dashed=1;" edge="1" source="svc_email" target="api_msgraph" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="conn_oauth_google" style="rounded=1;strokeColor=#34A853;strokeWidth=1;dashed=1;" edge="1" source="svc_oauth" target="api_oauth" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- Deploy arrows: Dev → Git → Staging → Prod -->
<mxCell id="conn_dev_git" value="git push" style="edgeStyle=orthogonalEdgeStyle;rounded=1;strokeColor=#78909C;strokeWidth=1;fontSize=9;fontColor=#78909C;dashed=1;" edge="1" source="dev_flask" target="git_github" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="conn_git_staging" value="git pull" style="edgeStyle=orthogonalEdgeStyle;rounded=1;strokeColor=#FF8F00;strokeWidth=1;fontSize=9;fontColor=#FF8F00;dashed=1;" edge="1" source="git_gitea" target="staging_flask" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="conn_git_prod" value="git pull" style="edgeStyle=orthogonalEdgeStyle;rounded=1;strokeColor=#1565C0;strokeWidth=1;fontSize=9;fontColor=#1565C0;dashed=1;" edge="1" source="git_gitea" target="flask" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<!-- ==================== LEGENDA ==================== -->
<mxCell id="legend_bg" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fafafa;strokeColor=#cccccc;" vertex="1" parent="1">
<mxGeometry x="1160" y="910" width="155" height="195" as="geometry"/>
</mxCell>
<mxCell id="legend_title" value="&lt;b&gt;Legenda&lt;/b&gt;" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=11;fontColor=#333;" vertex="1" parent="1">
<mxGeometry x="1170" y="915" width="70" height="20" as="geometry"/>
</mxCell>
<mxCell id="legend_1" value="&lt;font style=&quot;font-size:9px&quot;&gt;Zapora sieciowa&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=8;" vertex="1" parent="1">
<mxGeometry x="1170" y="940" width="130" height="20" as="geometry"/>
</mxCell>
<mxCell id="legend_2" value="&lt;font style=&quot;font-size:9px&quot;&gt;Strefa DMZ / Proxy&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=8;" vertex="1" parent="1">
<mxGeometry x="1170" y="965" width="130" height="20" as="geometry"/>
</mxCell>
<mxCell id="legend_3" value="&lt;font style=&quot;font-size:9px&quot;&gt;Aplikacja (produkcja)&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=8;" vertex="1" parent="1">
<mxGeometry x="1170" y="990" width="130" height="20" as="geometry"/>
</mxCell>
<mxCell id="legend_4" value="&lt;font style=&quot;font-size:9px&quot;&gt;Usługi wewnętrzne&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontSize=8;" vertex="1" parent="1">
<mxGeometry x="1170" y="1015" width="130" height="20" as="geometry"/>
</mxCell>
<mxCell id="legend_5" value="&lt;font style=&quot;font-size:9px&quot;&gt;Baza danych&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=8;" vertex="1" parent="1">
<mxGeometry x="1170" y="1040" width="130" height="20" as="geometry"/>
</mxCell>
<mxCell id="legend_6" value="&lt;font style=&quot;font-size:9px&quot;&gt;Staging (testowe)&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFF8E1;strokeColor=#FF8F00;fontSize=8;" vertex="1" parent="1">
<mxGeometry x="1170" y="1065" width="130" height="20" as="geometry"/>
</mxCell>
<mxCell id="legend_7" value="&lt;font style=&quot;font-size:9px&quot;&gt;Stacja deweloperska&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#E8F5E9;strokeColor=#4CAF50;fontSize=8;" vertex="1" parent="1">
<mxGeometry x="1170" y="1090" width="130" height="20" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>