File size: 14,920 Bytes
c4f5819
 
 
 
 
0cb4cc5
 
 
c4f5819
 
0cb4cc5
 
c4f5819
0cb4cc5
 
c4f5819
 
 
0cb4cc5
c4f5819
0cb4cc5
c4f5819
 
 
 
0cb4cc5
c4f5819
0cb4cc5
 
c4f5819
0cb4cc5
 
c4f5819
 
 
0cb4cc5
c4f5819
 
 
0cb4cc5
 
 
c4f5819
 
 
0cb4cc5
c4f5819
 
 
 
 
0cb4cc5
c4f5819
 
 
 
 
 
 
0cb4cc5
c4f5819
 
 
 
 
 
 
 
 
 
 
 
0cb4cc5
 
c4f5819
 
 
 
 
 
 
 
 
 
 
 
 
 
0cb4cc5
 
c4f5819
 
 
 
 
 
 
 
 
 
 
 
0cb4cc5
 
c4f5819
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0cb4cc5
c4f5819
 
 
 
 
 
 
 
 
 
 
 
0cb4cc5
c4f5819
 
 
 
 
 
 
 
 
 
0cb4cc5
c4f5819
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0cb4cc5
c4f5819
 
 
 
 
 
 
 
 
 
0cb4cc5
c4f5819
 
 
 
 
 
 
 
 
 
0cb4cc5
c4f5819
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ROGLAG · Tech Stack</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans+Thai:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
  :root{--bg:#0b0f17;--panel:#121826;--panel2:#0f1420;--line:#1f2a3d;--txt:#e6edf6;
    --muted:#aab8cc;--accent:#4da3ff;--accent2:#a78bfa;--teal:#5eead4;--ok:#34d399;--warn:#fbbf24;--crit:#f87171;--code:#0a0e16;
    --hair:rgba(148,163,184,0.18);}
  *{box-sizing:border-box}html{scroll-behavior:smooth}
  body{margin:0;background-color:#0b0f17;background:radial-gradient(1200px 600px at 80% -10%,#15203a 0%,var(--bg) 55%);
    color:var(--txt);font-family:"IBM Plex Sans Thai",-apple-system,"Segoe UI",sans-serif;line-height:1.65;font-size:16px}
  .wrap{max-width:1060px;margin:0 auto;padding:32px 22px 96px}
  header.hero{border:1px solid var(--line);border-radius:18px;padding:26px 30px;
    background:linear-gradient(135deg,#13203a,#0f1420);margin-bottom:14px}
  .hero h1{margin:0 0 6px;font-size:32px}.hero p{margin:0;color:var(--muted)}
  .chips{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}
  .chip{font-size:13px;padding:5px 11px;border:1px solid var(--line);border-radius:999px;background:#16203250;color:var(--teal)}
  nav.toc{position:sticky;top:0;z-index:5;backdrop-filter:blur(8px);background:#0b0f17cc;
    border:1px solid var(--line);border-radius:14px;padding:12px 16px;margin:18px 0 26px;display:flex;gap:14px;flex-wrap:wrap}
  nav.toc a{color:var(--muted);text-decoration:none;font-size:13px}nav.toc a:hover{color:var(--accent)}
  section{border:1px solid var(--line);border-radius:16px;padding:24px 26px;background:var(--panel);margin-bottom:22px}
  h2{font-size:22px;margin:0 0 10px;display:flex;align-items:center;gap:10px}
  h3{font-size:16px;margin:20px 0 8px;color:var(--accent)}
  .sub{color:var(--muted);margin:2px 0 16px;font-size:13px}
  small{font-size:12px;color:var(--muted)}
  code{background:var(--code);border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-size:13px;color:#cfe3ff;
    font-family:"IBM Plex Mono",ui-monospace,monospace}
  table{width:100%;border-collapse:collapse;margin:12px 0;font-size:13px}
  th,td{border:1px solid var(--line);padding:9px 12px;text-align:left;vertical-align:top}
  th{background:var(--panel2);color:var(--accent)}
  td b{color:#fff}
  .ver{color:var(--teal);font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:13px}
  .flow{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:14px 0;font-size:13px}
  .node{border:1px solid var(--line);background:var(--panel2);border-radius:10px;padding:8px 12px}
  .arrow{color:var(--accent2);font-weight:700}
  .callout{border:1px solid var(--hair);background:#0e1a2e;border-radius:10px;padding:12px 16px;margin:14px 0;font-size:13px}
  .callout.warn{background:#241d0e}
  .tag{display:inline-block;font-size:13px;padding:2px 8px;border-radius:999px;margin-left:6px}
  .t-now{background:#0e2a1e;color:var(--ok);border:1px solid #1c4b36}
  .t-prod{background:#241a2e;color:#c4a3ff;border:1px solid #3d2c4b}
  ul{margin:8px 0 8px 4px;padding-left:20px}li{margin:4px 0}
  footer{color:var(--muted);text-align:center;font-size:13px;margin-top:30px}
</style>
</head>
<body>
<div class="wrap">
  <header class="hero">
    <h1>🧱 ROGLAG · Tech Stack</h1>
    <p>สแตกจริงของระบบ Security Log RAG + Realtime Threat Console</p>
    <div class="chips">
      <span class="chip">Python 3.12</span><span class="chip">stdlib http.server</span>
      <span class="chip">Vanilla JS</span><span class="chip">Three.js</span>
      <span class="chip">Rule + RAG</span><span class="chip">FastAPI</span>
      <span class="chip">SQLAlchemy</span><span class="chip">Docker</span><span class="chip">OpenRouter</span>
    </div>
    <p style="margin-top:14px;font-size:13px;color:var(--muted)">
      <span class="tag t-now">NOW</span> ที่รันอยู่จริงในเดโม่ ·
      <span class="tag t-prod">PROD</span> สแตกระดับ production ที่อยู่ใน repo เดียวกัน
    </p>
  </header>

  <nav class="toc">
    <a href="#arch">สถาปัตยกรรม</a><a href="#fe">Frontend</a><a href="#be">Backend</a>
    <a href="#detect">Detection &amp; RAG</a><a href="#data">Data &amp; Generator</a>
    <a href="#prod">Production stack</a><a href="#ext">External</a><a href="#full">สรุปทั้งหมด</a>
  </nav>

  <section id="arch">
    <h2>ภาพรวมสถาปัตยกรรม</h2>
    <p class="sub">เดโม่ปัจจุบันเน้น zero-dependency รันได้ทันที, แต่ใน repo มีสแตก production พร้อมไปต่อ</p>
    <div class="flow">
      <span class="node">Log sources<br><small>auth/nginx/fw/system</small></span><span class="arrow"></span>
      <span class="node">Generator / CSV<br><small>ingest</small></span><span class="arrow"></span>
      <span class="node">Rule classifier<br><small>detect_rule</small></span><span class="arrow"></span>
      <span class="node">In-memory index<br><small>TF-IDF + vector</small></span><span class="arrow"></span>
      <span class="node">HTTP/JSON API</span><span class="arrow"></span>
      <span class="node">Dashboard<br><small>vanilla JS</small></span>
    </div>
    <div class="callout">
      เดโม่ใช้ <b>Python stdlib ล้วน</b> (ไม่ต้องลง dependency) เก็บ log ใน memory + ตอบ JSON API; ส่วน production ใช้ FastAPI + SQLAlchemy + Docker (หัวข้อ 6)
    </div>
  </section>

  <section id="fe">
    <h2>Frontend <span class="tag t-now">NOW</span></h2>
    <p class="sub">หน้าเดียว ไม่มี build step: โหลดเร็ว แก้ง่าย</p>
    <table>
      <tr><th>ส่วน</th><th>ใช้</th><th>หมายเหตุ</th></tr>
      <tr><td><b>Markup/Logic</b></td><td>HTML5 + Vanilla JavaScript (ES2020+)</td><td>ไฟล์เดียว <code>web/index.html</code> ไม่มี framework/bundler</td></tr>
      <tr><td><b>3D Globe</b></td><td>Three.js <span class="ver">0.160.0</span> (CDN)</td><td>WebGL globe + arcs + particles ในหน้า Overview</td></tr>
      <tr><td><b>Charts</b></td><td>SVG เขียนเอง</td><td>Threat activity graph (เส้น risk + bar severity) ไม่ใช้ chart lib</td></tr>
      <tr><td><b>Realtime monitor</b></td><td>Polling (fetch + setInterval)</td><td>tail-f log monitor, sort by time, ดึง events จาก ingest API</td></tr>
      <tr><td><b>Styling</b></td><td>CSS เขียนเอง (custom properties)</td><td>dark theme, ไม่มี Tailwind/Bootstrap</td></tr>
      <tr><td><b>Fonts</b></td><td>IBM Plex Mono + system fonts</td><td>โทน console/SOC</td></tr>
    </table>
  </section>

  <section id="be">
    <h2>Backend เดโม่ <span class="tag t-now">NOW</span></h2>
    <p class="sub"><code>server.py</code>: stdlib ล้วน ไม่มี dependency ภายนอก</p>
    <table>
      <tr><th>ส่วน</th><th>ใช้</th><th>หมายเหตุ</th></tr>
      <tr><td><b>Runtime</b></td><td>Python <span class="ver">3.12</span> (รองรับ 3.10+)</td><td>ใช้ type hints แบบ PEP 604</td></tr>
      <tr><td><b>HTTP server</b></td><td><code>http.server.ThreadingHTTPServer</code></td><td>stdlib, multithread, ไม่มี framework</td></tr>
      <tr><td><b>Storage</b></td><td>In-memory (Python lists/dicts)</td><td>โหลด JSONL เข้า RAM ตอน start + append สดผ่าน <code>add_rows()</code></td></tr>
      <tr><td><b>Vector store</b></td><td>SQLite <span class="ver">(stdlib sqlite3)</span></td><td><code>lograg_vectors.sqlite</code> เก็บ float32 embedding</td></tr>
      <tr><td><b>HTTP client</b></td><td><code>urllib.request</code></td><td>เรียก OpenRouter โดยไม่ต้องลง requests</td></tr>
    </table>
    <h3>API endpoints</h3>
    <table>
      <tr><th>Method</th><th>Path</th><th>หน้าที่</th></tr>
      <tr><td>GET</td><td><code>/api/health · /api/stats · /api/logs · /api/alerts</code></td><td>dashboard data</td></tr>
      <tr><td>POST</td><td><code>/api/search · /api/ask</code></td><td>RAG retrieval + Q&amp;A</td></tr>
      <tr><td>POST</td><td><code>/api/mock/emit</code></td><td>ยิง mock log realtime (คืน events)</td></tr>
      <tr><td>POST</td><td><code>/api/ingest/csv</code></td><td>อัปโหลด CSV → classify</td></tr>
      <tr><td>GET</td><td><code>/api/generate/csv</code></td><td>สร้าง CSV ใหม่ (unseeded)</td></tr>
    </table>
  </section>

  <section id="detect">
    <h2>Detection &amp; RAG <span class="tag t-now">NOW</span></h2>
    <table>
      <tr><th>ส่วน</th><th>ใช้</th><th>หมายเหตุ</th></tr>
      <tr><td><b>Classifier</b></td><td>Rule-based (regex patterns)</td><td><code>detect_rule()</code> → 7 categories + MITRE ATT&amp;CK + risk score, ทำงานออฟไลน์</td></tr>
      <tr><td><b>Keyword retrieval</b></td><td>TF-IDF เขียนเอง (postings + idf)</td><td>query expansion ไทย/อังกฤษ, ไม่ใช้ search engine</td></tr>
      <tr><td><b>Vector retrieval</b></td><td>cosine similarity (SQLite blobs)</td><td>optional, ใช้เมื่อมี index + API key</td></tr>
      <tr><td><b>Embeddings</b></td><td>OpenRouter <span class="ver">nvidia/llama-nemotron-embed</span></td><td>optional; fallback keyword เสมอ</td></tr>
      <tr><td><b>LLM answer</b></td><td>OpenRouter (<span class="ver">openrouter/free</span>)</td><td>optional; มี local rule-based summary สำรอง</td></tr>
    </table>
    <div class="callout warn">ทุกชั้นมี fallback: vector → keyword → rule-based local answer → ระบบไม่ล่มแม้ไม่มี API key</div>
  </section>

  <section id="data">
    <h2>Data &amp; Generator <span class="tag t-now">NOW</span></h2>
    <table>
      <tr><th>ส่วน</th><th>ใช้</th><th>หมายเหตุ</th></tr>
      <tr><td><b>Dataset</b></td><td>JSONL (synthetic security logs)</td><td>10k / 50k records, 7 categories</td></tr>
      <tr><td><b>Generator</b></td><td>Python (<code>app/generator.py</code>)</td><td>สุ่มไม่ซ้ำทุกครั้ง (unseeded), profile: mixed/attack/realistic</td></tr>
      <tr><td><b>CSV I/O</b></td><td><code>csv</code> stdlib</td><td>generate + ingest ผ่าน DictReader/DictWriter</td></tr>
      <tr><td><b>Categories</b></td><td>brute_force, port_scan, web_attack, priv_esc, data_exfil, c2_beacon, benign</td><td>map → MITRE + runbook</td></tr>
    </table>
  </section>

  <section id="prod">
    <h2>Production stack <span class="tag t-prod">PROD</span></h2>
    <p class="sub">อยู่ใน repo เดียวกัน (<code>app/</code> + Docker) สำหรับ deploy จริง / self-host เต็มรูปแบบ</p>
    <table>
      <tr><th>ชั้น</th><th>ใช้</th><th>เวอร์ชัน</th></tr>
      <tr><td><b>Web framework</b></td><td>FastAPI</td><td class="ver">0.115.6</td></tr>
      <tr><td><b>ASGI server</b></td><td>Uvicorn (standard)</td><td class="ver">0.34.0</td></tr>
      <tr><td><b>ORM / DB toolkit</b></td><td>SQLAlchemy (async)</td><td class="ver">2.0.36</td></tr>
      <tr><td><b>DB driver</b></td><td>asyncpg (Postgres) / aiosqlite (SQLite)</td><td class="ver">0.30.0 / 0.20.0</td></tr>
      <tr><td><b>HTTP client</b></td><td>httpx (async)</td><td class="ver">0.28.1</td></tr>
      <tr><td><b>File upload</b></td><td>python-multipart</td><td class="ver">0.0.20</td></tr>
      <tr><td><b>Realtime</b></td><td>WebSocket (FastAPI native)</td><td>fan-out broadcast in-process</td></tr>
      <tr><td><b>Database</b></td><td>PostgreSQL 16 / SQLite</td><td>portable ด้วย <code>DATABASE_URL</code></td></tr>
      <tr><td><b>Container</b></td><td>Docker + docker-compose</td><td>python:3.12-slim, postgres:16-alpine</td></tr>
    </table>
  </section>

  <section id="ext">
    <h2>External / Optional services</h2>
    <table>
      <tr><th>บริการ</th><th>ใช้ทำอะไร</th><th>สถานะ</th></tr>
      <tr><td><b>OpenRouter</b></td><td>LLM answer + embeddings</td><td>optional (มี local fallback)</td></tr>
      <tr><td><b>Qdrant</b></td><td>vector DB สำหรับ production RAG</td><td>optional (ตั้งผ่าน env)</td></tr>
      <tr><td><b>n8n</b></td><td>automation: alert → enrich → ticket/notify</td><td>แนะนำใน plan</td></tr>
      <tr><td><b>Vercel</b></td><td>deploy static + Python serverless (<code>api/*.py</code>)</td><td>มี <code>vercel.json</code></td></tr>
    </table>
  </section>

  <section id="full">
    <h2>สรุป Full Stack</h2>
    <table>
      <tr><th>Layer</th><th>เดโม่ (NOW)</th><th>Production (PROD)</th></tr>
      <tr><td><b>Frontend</b></td><td>Vanilla JS + Three.js + SVG</td><td>เหมือนเดิม (เพิ่ม WebSocket realtime)</td></tr>
      <tr><td><b>Backend</b></td><td>stdlib http.server</td><td>FastAPI + Uvicorn</td></tr>
      <tr><td><b>Storage</b></td><td>In-memory + SQLite</td><td>PostgreSQL (SQLAlchemy async)</td></tr>
      <tr><td><b>Realtime</b></td><td>Polling</td><td>WebSocket</td></tr>
      <tr><td><b>Retrieval</b></td><td>TF-IDF + SQLite vector</td><td>Qdrant / pgvector</td></tr>
      <tr><td><b>Detection</b></td><td>Rule-based (regex + MITRE)</td><td>เหมือนเดิม + ML ในอนาคต</td></tr>
      <tr><td><b>LLM</b></td><td>OpenRouter (optional)</td><td>OpenRouter / self-host Ollama</td></tr>
      <tr><td><b>Deploy</b></td><td>รันตรง <code>python3 server.py</code></td><td>Docker Compose / Vercel</td></tr>
      <tr><td><b>Automation</b></td><td>ไม่มี</td><td>n8n workflows</td></tr>
    </table>
    <div class="callout">ปรัชญา: <b>เดโม่ต้องรันได้ทันทีแบบ zero-dependency และออฟไลน์</b> แล้วค่อยสเกลขึ้น production ด้วยสแตกที่เตรียมไว้ในโปรเจกต์เดียวกัน</div>
  </section>

  <footer>ROGLAG · Tech Stack · ดู <a href="/plan" style="color:var(--accent)">/plan</a> สำหรับแผนยกระดับ production</footer>
</div>
</body>
</html>