Skip to content

Commit 337bfe6

Browse files
committed
J시리즈 마무리, 리드미 재작성
1 parent d478de4 commit 337bfe6

4 files changed

Lines changed: 265 additions & 180 deletions

File tree

README.en.md

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ flowchart LR
7878
STR["UI operational state (in-memory)<br/>asset_owners / asset_audit_log / vuln_actions<br/>triage_store / incident_store / user_profiles"]
7979
end
8080
81-
subgraph API["MORI API (api/server.py)"]
82-
EP["FastAPI endpoints<br/>/dashboard /assets /alerts<br/>/vulnerabilities /incidents<br/>/compliance /reports /interpret /query"]
81+
subgraph API["MORI API (api/)"]
82+
SRV["server.py<br/>orchestrator (888 lines)<br/>builds RouteContext + registers modules"]
83+
RT["routes/ package (16 domain modules)<br/>auth · assets · alerts · vulnerabilities<br/>incidents · compliance · query · pages<br/>rbac · audit · plans · guides · sources<br/>webhooks · dashboard_prefs"]
8384
UI["Unified ops UI (/ui)<br/>Overview · Assets · Trivy · Triage<br/>Incidents · Compliance · Reports"]
8485
end
8586
@@ -103,18 +104,21 @@ flowchart LR
103104
104105
MEM --> V & QS & RP
105106
QC --> QS
106-
STR <--> EP
107+
SRV --> RT
108+
STR <-->|RouteContext| RT
107109
108-
V & QS & RP --> EP
109-
EP --> UI
110-
EP --> CSV
110+
V & QS & RP --> RT
111+
RT --> UI
112+
RT --> CSV
111113
UI --> AUD
112114
113115
PG --> MEM
114116
STR -.Phase 2 persistence planned.-> PG
115117
```
116118

117119
> Solid lines = current operating flow. PostgreSQL holds **normalized seed data** (hosts/alerts/vulns/observations) which is loaded into InMemoryRepository at boot for queries. The 6 UI operational stores (triage / incidents / asset owners / vuln actions / asset audit log / user profiles) currently run in-memory; the **dashed line = next milestone (Postgres persistence + activating real-time pollers)**.
120+
>
121+
> **API structure (Task J done):** `server.py` is now a **thin orchestrator (888 lines)** that assembles in-memory state and helper closures into a `RouteContext`, then registers 16 domain modules. Each endpoint is owned by `register_<domain>(ctx)` in `routes/<domain>.py`, and the 6 in-memory stores are shared across modules via the `RouteContext`.
118122
119123
---
120124

@@ -272,7 +276,17 @@ Deployment behavior: `docker compose down && docker compose up -d` (GitHub Actio
272276
```text
273277
src/mori_soc/
274278
├── api/
275-
│ ├── server.py ← FastAPI endpoints + unified ops UI (/ui) HTML/JS
279+
│ ├── server.py ← thin orchestrator (888 lines): builds RouteContext + registers modules
280+
│ ├── routes/ ← 16 domain route modules (register_<domain>(ctx))
281+
│ │ ├── context.py ← RouteContext (stores + helper closures, ~35 fields)
282+
│ │ ├── auth.py · assets.py · alerts.py · vulnerabilities.py
283+
│ │ ├── incidents.py · compliance.py · query.py · pages.py
284+
│ │ ├── rbac.py · audit.py · plans.py · guides.py · sources.py
285+
│ │ └── webhooks.py · dashboard_prefs.py
286+
│ ├── templates.py ← /ui · /login · dashboard · console HTML/JS renderers
287+
│ ├── payloads.py ← dashboard/pdca/query payload builders
288+
│ ├── i18n.py ← UI localization strings
289+
│ ├── auth.py ← session middleware · credential verify · default role perms
276290
│ └── contracts.py ← QueryRequest/Response, EvidenceRef, QueryScope
277291
├── collectors/ ← Fleet · Wazuh · Zabbix · Trivy · LDAP collectors
278292
├── pollers/ ← Per-source periodic pollers (worker.py orchestrates)
@@ -297,7 +311,7 @@ src/mori_soc/
297311
| Storage area | Current status | Location |
298312
|---|---|---|
299313
| **Normalized security data** (hosts / alerts / vulnerabilities / observations / fleet_query_results / control_checks / directory_accounts / source_syncs …) | PostgreSQL **seed schema + seed data** loaded. Boot-time load into InMemoryRepository for queries | `schema/001_phase1_initial.sql`, `repositories/postgres.py`, `repositories/memory.py` |
300-
| **UI operational state — 6 in-memory stores** (reset on restart) | Module-scope dicts in API process. Postgres persistence not yet connected | `api/server.py` |
314+
| **UI operational state — 6 in-memory stores** (reset on restart) | Created by `server.py`, injected via `RouteContext`, shared/mutated by domain route modules. Postgres persistence not yet connected | `api/server.py``api/routes/context.py` |
301315
| Phase 2 persistence (6 stores → Postgres) | 🔲 Planned — mapping code/schema ready in `schema/002_phase2_compliance_identity.sql` + `repositories/postgres.py` ||
302316

303317
#### In-memory 6-store detail
@@ -428,15 +442,22 @@ curl -OJ "http://localhost:18000/compliance/reports/monthly_operations?format=pd
428442
docker compose restart mori-api # Reload snapshot after restore
429443
```
430444

431-
### Code validation (when editing server.py)
445+
### Code validation (when editing routes / templates)
432446

433-
`server.py` is very large and contains HTML/JS inside Python triple-quoted strings. Always validate after edits:
447+
Task J split routes into `api/routes/` and HTML/JS renderers into `api/templates.py`. To guarantee a lossless refactor, run the **3-gate check** after changes:
434448

435449
```bash
436-
python3 -c "import ast; ast.parse(open('src/mori_soc/api/server.py').read()); print('AST OK')"
450+
# 1) OpenAPI route diff — registered paths/methods/schema match the baseline
451+
# compare _routes_snapshot.py output against _routes_baseline.json → must be IDENTICAL
452+
# 2) Rendered-template SHA — 6 hashes (login/signup/dashboard/console) match baseline
453+
# python /app/_verify_templates.py
454+
# 3) Full unit-test suite
455+
docker compose run --rm --no-deps -e MORI_DEMO_SEED=0 \
456+
-v "$(pwd)/tests:/app/tests" -v "$(pwd)/src:/app/src" \
457+
mori-api python -m unittest discover -s tests # → 115 OK (skipped=2)
437458
```
438459

439-
Additionally, a helper script that verifies brace balance in `<script>...</script>` blocks (used during the Audit-Ready work in this README) can catch JS breakage before runtime.
460+
Each domain's routes are owned by `register_<domain>(ctx)` in `routes/<domain>.py`; shared state/helpers are injected via the `RouteContext` in `routes/context.py`.
440461

441462
---
442463

@@ -581,7 +602,7 @@ MORI SOC combines open-source security tools to provide a single ops screen, wit
581602

582603
| ID | Work | Status |
583604
|---|---|---|
584-
| **J** (foundation) | Split `server.py` (~9,200 lines) into modules — i18n / templates / auth / routes. A refactor that lowers regression risk for the persistence/poller work that follows | 🔲 Next |
605+
| **J** (foundation) | Split `server.py` into modules — i18n / templates / auth / payloads + a `routes/` package (16 domain modules, `RouteContext`). **2,962→888 lines (-70%)**, lossless-verified (OpenAPI diff · SHA · 115 tests). A refactor that lowers regression risk for the persistence/poller work that follows | ✅ Done |
585606
| **M2-1** | Persist the 6 UI operational state stores (`asset_owners`·`asset_audit_log`·`vuln_actions`·`triage_store`·`incident_store`·`user_profiles`) to PostgreSQL (`repositories/postgres.py` + `schema/002_*.sql`) | 🔲 Top priority |
586607
| **M2-2** | Zabbix API polling integration verification — trigger/item → ingestion → alert/observation → triage → incident | 🟡 Collector done, verifying |
587608
| **M2-3** | Fleet / Wazuh REST poller connection — host/osquery·alert → asset/triage, reflect `source_syncs` freshness | 🔲 Parser·Collector ready |
@@ -631,7 +652,9 @@ Fastest context-restoration prompt when continuing work in a different environme
631652
This repo is MORI SOC-lite (Audit-Ready Compliance-Evidence Platform).
632653
Phase 1 (data collection/normalization core) is complete; Phase 2 (ops query
633654
engine + ops UI) is in Alpha. Read the "Current Status at a Glance" section of
634-
the README, src/mori_soc/api/server.py, docs/SECURITY_DATA_QUERY_PLATFORM.md,
655+
Task J (server.py modularization) is done — the API is now src/mori_soc/api/server.py
656+
(orchestrator) + src/mori_soc/api/routes/ (16 domain modules, RouteContext).
657+
Read the README, routes/context.py, docs/SECURITY_DATA_QUERY_PLATFORM.md,
635658
and schema/*.sql, then continue with the next priorities (persistence + real-time polling).
636659
```
637660

README.md

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ flowchart LR
7878
STR["UI 운영 상태 (인메모리)<br/>asset_owners / asset_audit_log / vuln_actions<br/>triage_store / incident_store / user_profiles"]
7979
end
8080
81-
subgraph API["MORI API (api/server.py)"]
82-
EP["FastAPI 엔드포인트<br/>/dashboard /assets /alerts<br/>/vulnerabilities /incidents<br/>/compliance /reports /interpret /query"]
81+
subgraph API["MORI API (api/)"]
82+
SRV["server.py<br/>오케스트레이터 (888줄)<br/>RouteContext 조립 + 모듈 등록"]
83+
RT["routes/ 패키지 (16 도메인 모듈)<br/>auth · assets · alerts · vulnerabilities<br/>incidents · compliance · query · pages<br/>rbac · audit · plans · guides · sources<br/>webhooks · dashboard_prefs"]
8384
UI["통합 운영 UI (/ui)<br/>Overview · Assets · Trivy · Triage<br/>Incidents · Compliance · Reports"]
8485
end
8586
@@ -103,18 +104,21 @@ flowchart LR
103104
104105
MEM --> V & QS & RP
105106
QC --> QS
106-
STR <--> EP
107+
SRV --> RT
108+
STR <-->|RouteContext| RT
107109
108-
V & QS & RP --> EP
109-
EP --> UI
110-
EP --> CSV
110+
V & QS & RP --> RT
111+
RT --> UI
112+
RT --> CSV
111113
UI --> AUD
112114
113115
PG --> MEM
114116
STR -.Phase 2 영속화 예정.-> PG
115117
```
116118

117119
> 실선은 현재 운영 중인 흐름. PostgreSQL은 **정규화 시드 데이터**(hosts/alerts/vulns/observations)를 보유하며 부팅 시 InMemoryRepository로 로드되어 질의에 사용됩니다. UI 운영 상태(triage / incidents / asset owners / vuln actions / asset audit log / user profiles) 6종은 현재 인메모리에서 동작하며, **점선 = 다음 마일스톤(Postgres 영속화 + 실시간 폴러 활성화)** 입니다.
120+
>
121+
> **API 구조(Task J 완료):** `server.py`는 인메모리 상태와 헬퍼 클로저를 `RouteContext`로 조립한 뒤 16개 도메인 모듈을 등록하는 **얇은 오케스트레이터(888줄)** 로 슬림화되었습니다. 각 엔드포인트는 `routes/<domain>.py``register_<domain>(ctx)`가 소유하며, 인메모리 6종 store는 `RouteContext`를 통해 모듈 간 공유됩니다.
118122
119123
---
120124

@@ -270,7 +274,17 @@ flowchart LR
270274
```text
271275
src/mori_soc/
272276
├── api/
273-
│ ├── server.py ← FastAPI 엔드포인트 + 통합 운영 UI(/ui) HTML/JS
277+
│ ├── server.py ← 얇은 오케스트레이터(888줄): RouteContext 조립 + 모듈 등록
278+
│ ├── routes/ ← 16개 도메인 라우트 모듈 (register_<domain>(ctx))
279+
│ │ ├── context.py ← RouteContext (store + 헬퍼 클로저 ~35 필드)
280+
│ │ ├── auth.py · assets.py · alerts.py · vulnerabilities.py
281+
│ │ ├── incidents.py · compliance.py · query.py · pages.py
282+
│ │ ├── rbac.py · audit.py · plans.py · guides.py · sources.py
283+
│ │ └── webhooks.py · dashboard_prefs.py
284+
│ ├── templates.py ← /ui · /login · 대시보드 · 콘솔 HTML/JS 렌더러
285+
│ ├── payloads.py ← dashboard/pdca/query payload 빌더
286+
│ ├── i18n.py ← UI 다국어 문자열
287+
│ ├── auth.py ← 세션 미들웨어 · 자격증명 검증 · 역할 기본 권한
274288
│ └── contracts.py ← QueryRequest/Response, EvidenceRef, QueryScope
275289
├── collectors/ ← Fleet · Wazuh · Zabbix · Trivy · LDAP 수집기
276290
├── pollers/ ← 각 소스별 주기 폴러 (worker.py 가 오케스트레이션)
@@ -295,7 +309,7 @@ src/mori_soc/
295309
| 저장 영역 | 현재 상태 | 위치 |
296310
|---|---|---|
297311
| **Normalized security data** (hosts / alerts / vulnerabilities / observations / fleet_query_results / control_checks / directory_accounts / source_syncs …) | PostgreSQL **시드 스키마 + 시드 데이터** 적재. 부팅 시 InMemoryRepository로 로드되어 질의에 사용 | `schema/001_phase1_initial.sql`, `repositories/postgres.py`, `repositories/memory.py` |
298-
| **UI operational state — 인메모리 6종** (재시작 시 초기화) | API 프로세스의 모듈 스코프 dict로 동작 중. Postgres 영속화 미연결 | `api/server.py` |
312+
| **UI operational state — 인메모리 6종** (재시작 시 초기화) | `server.py`가 생성해 `RouteContext`로 주입, 도메인 라우트 모듈이 공유·변경. Postgres 영속화 미연결 | `api/server.py``api/routes/context.py` |
299313
| Phase 2 영속화 (6종 store → Postgres) | 🔲 Planned — `schema/002_phase2_compliance_identity.sql` + `repositories/postgres.py`에 매핑 코드/스키마 준비됨 ||
300314

301315
#### 인메모리 6종 store 상세
@@ -426,15 +440,22 @@ curl -OJ "http://localhost:18000/compliance/reports/monthly_operations?format=pd
426440
docker compose restart mori-api # 복원 후 snapshot 재로드
427441
```
428442

429-
### 코드 검증 (server.py 변경 시)
443+
### 코드 검증 (라우트 / 템플릿 변경 시)
430444

431-
`server.py`는 매우 크고 HTML/JS가 Python triple-quoted string 안에 포함됩니다. 편집항상 다음 검증을 수행합니다.
445+
Task J로 라우트는 `api/routes/`로, HTML/JS 렌더러는 `api/templates.py`로 분리되었습니다. 무손실 리팩터를 보장하기 위해 변경**3중 게이트** 수행합니다.
432446

433447
```bash
434-
python3 -c "import ast; ast.parse(open('src/mori_soc/api/server.py').read()); print('AST OK')"
448+
# 1) OpenAPI 라우트 diff — 등록된 경로/메서드/스키마가 baseline과 동일한지
449+
# _routes_snapshot.py 출력과 _routes_baseline.json 비교 → IDENTICAL 이어야 함
450+
# 2) 렌더 템플릿 SHA — login/signup/dashboard/console 6종 해시가 baseline과 일치
451+
# python /app/_verify_templates.py
452+
# 3) 전체 단위 테스트
453+
docker compose run --rm --no-deps -e MORI_DEMO_SEED=0 \
454+
-v "$(pwd)/tests:/app/tests" -v "$(pwd)/src:/app/src" \
455+
mori-api python -m unittest discover -s tests # → 115 OK (skipped=2)
435456
```
436457

437-
추가로 `<script>...</script>` 블록의 중괄호 균형을 확인하는 헬퍼 스크립트(이 README의 Audit-Ready 작업에서 사용)를 활용해 JS 깨짐 여부를 사전에 잡을 수 있습니다.
458+
각 도메인 라우트는 `routes/<domain>.py``register_<domain>(ctx)`가 소유하며, 공유 상태/헬퍼는 `routes/context.py``RouteContext`를 통해 주입됩니다.
438459

439460
---
440461

@@ -575,7 +596,7 @@ MORI SOC는 오픈소스 보안 도구를 결합해 단일 운영 화면을 제
575596

576597
| ID | 작업 | 상태 |
577598
|---|---|---|
578-
| **J** (기반) | `server.py`(~9,200줄) 모듈 분리 — i18n / templates / auth / routes. 이후 영속화·폴러 작업의 회귀 위험을 낮추는 리팩터 기반 | 🔲 다음 |
599+
| **J** (기반) | `server.py` 모듈 분리 — i18n / templates / auth / payloads + `routes/` 패키지(16 도메인 모듈, `RouteContext`). **2,962→888줄(-70%)**, 무손실 검증(OpenAPI diff·SHA·115 테스트). 이후 영속화·폴러 작업의 회귀 위험을 낮추는 리팩터 기반 | ✅ 완료 |
579600
| **M2-1** | UI 운영 상태 6종 store(`asset_owners`·`asset_audit_log`·`vuln_actions`·`triage_store`·`incident_store`·`user_profiles`) → PostgreSQL 영속화 (`repositories/postgres.py` + `schema/002_*.sql`) | 🔲 최우선 |
580601
| **M2-2** | Zabbix API polling 통합 검증 — trigger/item → ingestion → alert/observation → triage → incident | 🟡 Collector 완료, 검증 중 |
581602
| **M2-3** | Fleet / Wazuh REST poller 연결 — host/osquery·alert → asset/triage, `source_syncs` freshness 반영 | 🔲 Parser·Collector 준비됨 |
@@ -624,7 +645,9 @@ MORI SOC는 오픈소스 보안 도구를 결합해 단일 운영 화면을 제
624645
```
625646
이 저장소는 MORI SOC-lite (Audit-Ready Compliance-Evidence Platform).
626647
Phase 1(데이터 수집/정규화 코어) 완료, Phase 2(관제 질의 엔진 + 운영 UI) Alpha 운영 중.
627-
README의 "현재 상태 한눈에 보기"와 src/mori_soc/api/server.py,
648+
Task J(server.py 모듈 분리) 완료 — API는 src/mori_soc/api/server.py(오케스트레이터)
649+
+ src/mori_soc/api/routes/ (16 도메인 모듈, RouteContext) 구조.
650+
README의 "현재 상태 한눈에 보기", routes/context.py,
628651
docs/SECURITY_DATA_QUERY_PLATFORM.md, schema/*.sql을 확인하고
629652
다음 우선순위(영속화 + 실시간 폴링)를 이어서 진행해줘.
630653
```

0 commit comments

Comments
 (0)