kcg-ai-monitoring/frontend/src/flow/manifest/edges.json
htlee a6f6003c5f feat: System Flow 뷰어 추가 (system-flow.html) — 102 노드, 133 엣지
iran 프로젝트의 gear-parent-flow 패턴을 차용하여 시스템 전체 데이터 흐름을
노드/엣지로 시각화하는 별도 React 앱 추가. 메인 SPA와 완전 분리.

## 인프라
- @xyflow/react 추가
- frontend/system-flow.html (별도 entry HTML)
- frontend/src/systemFlowMain.tsx (React entry)
- vite.config.ts: rollupOptions.input에 systemFlow 추가
- 빌드 산출물: dist/system-flow.html + dist/assets/systemFlow-*.js (231kB, 메인과 분리)

## 매니페스트 (frontend/src/flow/manifest/)
카테고리별 JSON 분할 + 빌드 시 병합:
- 01-ingest.json (6) — snpdb, vessel_store, refresh
- 02-pipeline.json (7) — 7단계 분류 파이프라인
- 03-algorithms.json (12) — zone/dark/spoofing/risk/transship 등
- 04-fleet.json (9) — fleet_tracker, polygon_builder, gear_correlation, parent_inference
- 05-output.json (8) — event/violation/kpi/stats/alert/redis
- 06-storage.json (18) — 핵심 DB 테이블
- 07-backend.json (15) — Spring Boot 컨트롤러 + endpoint
- 08-frontend.json (17) — 프론트 화면 (menu 매핑 포함)
- 09-decision.json (8) — 운영자 의사결정 액션
- 10-external.json (2) — iran, redis
- edges.json (133) — data/trigger/feedback 분류

## 뷰어 컴포넌트
- SystemFlowViewer.tsx — 3단 레이아웃 + React Flow + 상태 관리
- components/FilterBar.tsx — 검색/단계/메뉴/상세필터 + 레이아웃 토글
- components/NodeListSidebar.tsx — 좌측 카테고리별 노드 리스트
- components/NodeDetailPanel.tsx — 우측 선택 정보 + incoming/outgoing 흐름
- components/nodeShapes.ts — kind별 모양/색상 헬퍼
- SystemFlowViewer.css — 전용 다크 테마 스타일

## 기능
- stage(단계) ⇄ menu(메뉴) 두 가지 그룹화 토글
- 통합 검색 (label/file/symbol/tag)
- 다중 필터 (kind/trigger/status)
- 노드 모양: kind별 (algorithm=다이아몬드, decision=마름모, api=6각형 등)
- 엣지 색상: data=회색, trigger=녹색, feedback=노란 점선
- 딥링크: /system-flow.html#node=<id> (산출문서에서 직접 참조)

## /version 스킬 통합
- CLAUDE.md에 "/version 스킬 사후 처리" 섹션 추가
  Claude가 /version 호출 후 자동으로 manifest.meta version/updatedAt/releaseDate 갱신
- .gitea/workflows/deploy.yml에 archive 보존 단계 추가
  /deploy/kcg-ai-monitoring-archive/system-flow/v{version}_{date}/ 영구 누적
  (nginx 노출 X, 서버 로컬 보존)
- docs/system-flow-guide.md 작성 (URL, 노드 ID 명명, 산출문서 참조법, 갱신 절차)

## URL
- 운영: https://kcg-ai-monitoring.gc-si.dev/system-flow.html
- 메인 SPA에 링크 노출 없음 (개발 단계 페이지)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:10:22 +09:00

150 lines
17 KiB
JSON

[
{ "id": "e_snpdb__initial_load", "source": "ingest.snpdb_5min", "target": "ingest.snpdb_initial_load", "label": "SELECT 24h", "kind": "data" },
{ "id": "e_snpdb__incremental", "source": "ingest.snpdb_5min", "target": "ingest.snpdb_incremental", "label": "SELECT > last_bucket", "kind": "data" },
{ "id": "e_initial__store", "source": "ingest.snpdb_initial_load", "target": "ingest.vessel_store_cache", "label": "초기 적재", "kind": "data" },
{ "id": "e_incremental__store", "source": "ingest.snpdb_incremental", "target": "ingest.vessel_store_cache", "label": "merge_incremental", "kind": "data" },
{ "id": "e_static__store", "source": "ingest.static_info_refresh", "target": "ingest.vessel_store_cache", "label": "정적정보", "kind": "data" },
{ "id": "e_permit__store", "source": "ingest.permit_registry_refresh", "target": "ingest.vessel_store_cache", "label": "허가 set", "kind": "data" },
{ "id": "e_store__preprocess", "source": "ingest.vessel_store_cache", "target": "pipeline.preprocess", "label": "select_targets", "kind": "data" },
{ "id": "e_preprocess__behavior", "source": "pipeline.preprocess", "target": "pipeline.behavior_detect", "kind": "data" },
{ "id": "e_behavior__resample", "source": "pipeline.behavior_detect", "target": "pipeline.resample", "kind": "data" },
{ "id": "e_resample__feature", "source": "pipeline.resample", "target": "pipeline.feature_extract", "kind": "data" },
{ "id": "e_feature__classify", "source": "pipeline.feature_extract", "target": "pipeline.classify", "kind": "data" },
{ "id": "e_classify__cluster", "source": "pipeline.classify", "target": "pipeline.cluster", "kind": "data" },
{ "id": "e_cluster__seasonal", "source": "pipeline.cluster", "target": "pipeline.seasonal_tag", "kind": "data" },
{ "id": "e_cluster__zone", "source": "pipeline.cluster", "target": "algo.zone_classify", "kind": "data" },
{ "id": "e_cluster__ucaf", "source": "pipeline.cluster", "target": "algo.ucaf_score", "kind": "data" },
{ "id": "e_cluster__ucft", "source": "pipeline.cluster", "target": "algo.ucft_score", "kind": "data" },
{ "id": "e_cluster__trawl", "source": "pipeline.cluster", "target": "algo.trawl_uturn", "kind": "data" },
{ "id": "e_cluster__dark", "source": "pipeline.cluster", "target": "algo.dark_vessel", "kind": "data" },
{ "id": "e_cluster__spoof", "source": "pipeline.cluster", "target": "algo.spoofing_score", "kind": "data" },
{ "id": "e_cluster__jumps", "source": "pipeline.cluster", "target": "algo.speed_jumps", "kind": "data" },
{ "id": "e_cluster__bd09", "source": "pipeline.cluster", "target": "algo.bd09_offset", "kind": "data" },
{ "id": "e_cluster__risk", "source": "pipeline.cluster", "target": "algo.risk_score", "kind": "data" },
{ "id": "e_store__lwrisk", "source": "ingest.vessel_store_cache", "target": "algo.lightweight_risk", "label": "412* 미통과 선박", "kind": "data" },
{ "id": "e_store__transship", "source": "ingest.vessel_store_cache", "target": "algo.transship_detect", "kind": "data" },
{ "id": "e_cluster__similarity", "source": "pipeline.cluster", "target": "algo.track_similarity", "kind": "data" },
{ "id": "e_zone__results", "source": "algo.zone_classify", "target": "storage.vessel_analysis_results", "kind": "data" },
{ "id": "e_ucaf__results", "source": "algo.ucaf_score", "target": "storage.vessel_analysis_results", "kind": "data" },
{ "id": "e_ucft__results", "source": "algo.ucft_score", "target": "storage.vessel_analysis_results", "kind": "data" },
{ "id": "e_dark__results", "source": "algo.dark_vessel", "target": "storage.vessel_analysis_results", "kind": "data" },
{ "id": "e_spoof__results", "source": "algo.spoofing_score", "target": "storage.vessel_analysis_results", "kind": "data" },
{ "id": "e_jumps__results", "source": "algo.speed_jumps", "target": "storage.vessel_analysis_results", "kind": "data" },
{ "id": "e_bd09__results", "source": "algo.bd09_offset", "target": "storage.vessel_analysis_results", "kind": "data" },
{ "id": "e_risk__results", "source": "algo.risk_score", "target": "storage.vessel_analysis_results", "kind": "data" },
{ "id": "e_lwrisk__results", "source": "algo.lightweight_risk", "target": "storage.vessel_analysis_results", "kind": "data" },
{ "id": "e_transship__results", "source": "algo.transship_detect", "target": "storage.vessel_analysis_results", "kind": "data" },
{ "id": "e_cluster__fleet_load", "source": "pipeline.cluster", "target": "fleet.load_registry", "kind": "trigger" },
{ "id": "e_fleet_load__match", "source": "fleet.load_registry", "target": "fleet.match_ais_to_registry", "kind": "data" },
{ "id": "e_match__gear_identity", "source": "fleet.match_ais_to_registry", "target": "fleet.track_gear_identity", "kind": "data" },
{ "id": "e_gear_identity__clusters", "source": "fleet.track_gear_identity", "target": "fleet.build_clusters", "kind": "data" },
{ "id": "e_clusters__snapshot", "source": "fleet.build_clusters", "target": "fleet.save_snapshot", "kind": "data" },
{ "id": "e_snapshot__store", "source": "fleet.save_snapshot", "target": "storage.fleet_tracking_snapshot", "label": "INSERT", "kind": "data" },
{ "id": "e_snapshot__detect_groups", "source": "fleet.save_snapshot", "target": "fleet.detect_gear_groups", "kind": "trigger" },
{ "id": "e_detect__polygons", "source": "fleet.detect_gear_groups", "target": "fleet.build_polygons", "kind": "data" },
{ "id": "e_polygons__store", "source": "fleet.build_polygons", "target": "storage.group_polygon_snapshots", "label": "INSERT", "kind": "data" },
{ "id": "e_polygons__correlation", "source": "fleet.build_polygons", "target": "fleet.gear_correlation", "kind": "data" },
{ "id": "e_correlation__scores", "source": "fleet.gear_correlation", "target": "storage.gear_correlation_scores", "label": "UPSERT", "kind": "data" },
{ "id": "e_correlation__inference", "source": "fleet.gear_correlation", "target": "fleet.parent_inference", "kind": "data" },
{ "id": "e_inference__resolution", "source": "fleet.parent_inference", "target": "storage.gear_group_parent_resolution", "label": "UPSERT", "kind": "data" },
{ "id": "e_companies__load", "source": "storage.fleet_companies", "target": "fleet.load_registry", "kind": "data" },
{ "id": "e_vessels__load", "source": "storage.fleet_vessels", "target": "fleet.load_registry", "kind": "data" },
{ "id": "e_identity__store", "source": "fleet.track_gear_identity", "target": "storage.fleet_tracking_snapshot", "kind": "data" },
{ "id": "e_results__violation", "source": "storage.vessel_analysis_results", "target": "output.violation_classifier", "kind": "data" },
{ "id": "e_violation__event", "source": "output.violation_classifier", "target": "output.event_generator", "kind": "data" },
{ "id": "e_event__events_store", "source": "output.event_generator", "target": "storage.prediction_events", "label": "INSERT", "kind": "data" },
{ "id": "e_event__workflow", "source": "output.event_generator", "target": "storage.event_workflow", "label": "INIT", "kind": "data" },
{ "id": "e_results__kpi", "source": "storage.vessel_analysis_results", "target": "output.kpi_writer", "kind": "data" },
{ "id": "e_kpi__store", "source": "output.kpi_writer", "target": "storage.prediction_kpi_realtime", "label": "UPSERT", "kind": "data" },
{ "id": "e_results__hourly", "source": "storage.vessel_analysis_results", "target": "output.stats_hourly", "kind": "data" },
{ "id": "e_hourly__store", "source": "output.stats_hourly", "target": "storage.prediction_stats_hourly", "label": "INSERT", "kind": "data" },
{ "id": "e_results__daily", "source": "storage.vessel_analysis_results", "target": "output.stats_daily", "kind": "data" },
{ "id": "e_daily__store", "source": "output.stats_daily", "target": "storage.prediction_stats_daily", "label": "INSERT", "kind": "data" },
{ "id": "e_daily__monthly", "source": "output.stats_daily", "target": "output.stats_monthly", "kind": "trigger" },
{ "id": "e_monthly__store", "source": "output.stats_monthly", "target": "storage.prediction_stats_monthly", "label": "INSERT", "kind": "data" },
{ "id": "e_events__alert", "source": "storage.prediction_events", "target": "output.alert_dispatcher", "kind": "data" },
{ "id": "e_alert__store", "source": "output.alert_dispatcher", "target": "storage.prediction_alerts", "label": "INSERT", "kind": "data" },
{ "id": "e_results__chat_cache", "source": "storage.vessel_analysis_results", "target": "output.redis_chat_cache", "kind": "data" },
{ "id": "e_chat_cache__redis", "source": "output.redis_chat_cache", "target": "external.redis", "label": "SET", "kind": "data" },
{ "id": "e_events__api_get", "source": "storage.prediction_events", "target": "api.events_get", "label": "SELECT", "kind": "data" },
{ "id": "e_alerts__api_get", "source": "storage.prediction_alerts", "target": "api.alerts_get", "label": "SELECT", "kind": "data" },
{ "id": "e_kpi__api", "source": "storage.prediction_kpi_realtime", "target": "api.stats_kpi", "label": "SELECT", "kind": "data" },
{ "id": "e_hourly__api", "source": "storage.prediction_stats_hourly", "target": "api.stats_hourly", "kind": "data" },
{ "id": "e_daily__api", "source": "storage.prediction_stats_daily", "target": "api.stats_daily", "kind": "data" },
{ "id": "e_monthly__api", "source": "storage.prediction_stats_monthly", "target": "api.stats_monthly", "kind": "data" },
{ "id": "e_resolution__api_review", "source": "storage.gear_group_parent_resolution", "target": "api.parent_inference_review", "kind": "data" },
{ "id": "e_exclusions__api", "source": "storage.gear_parent_candidate_exclusions", "target": "api.parent_inference_exclusions", "kind": "data" },
{ "id": "e_label_sessions__api", "source": "storage.gear_parent_label_sessions", "target": "api.parent_inference_label_sessions", "kind": "data" },
{ "id": "e_enf_records__api", "source": "storage.enforcement_records", "target": "api.enforcement_records", "kind": "data" },
{ "id": "e_enf_plans__api", "source": "storage.enforcement_plans", "target": "api.enforcement_plans", "kind": "data" },
{ "id": "e_iran__vessel_analysis_api", "source": "external.iran_backend", "target": "api.vessel_analysis", "label": "프록시", "kind": "data" },
{ "id": "e_api_events__dashboard", "source": "api.events_get", "target": "ui.dashboard", "kind": "data" },
{ "id": "e_api_events__event_list", "source": "api.events_get", "target": "ui.event_list", "kind": "data" },
{ "id": "e_api_events__china", "source": "api.events_get", "target": "ui.china_fishing", "kind": "data" },
{ "id": "e_api_events__transfer", "source": "api.events_get", "target": "ui.transfer_detection", "kind": "data" },
{ "id": "e_api_alerts__dashboard", "source": "api.alerts_get", "target": "ui.dashboard", "kind": "data" },
{ "id": "e_api_alerts__field", "source": "api.alerts_get", "target": "ui.ai_alert", "kind": "data" },
{ "id": "e_api_kpi__dashboard", "source": "api.stats_kpi", "target": "ui.dashboard", "kind": "data" },
{ "id": "e_api_kpi__monitoring", "source": "api.stats_kpi", "target": "ui.monitoring_dashboard", "kind": "data" },
{ "id": "e_api_kpi__statistics", "source": "api.stats_kpi", "target": "ui.statistics", "kind": "data" },
{ "id": "e_api_hourly__dashboard", "source": "api.stats_hourly", "target": "ui.dashboard", "kind": "data" },
{ "id": "e_api_hourly__monitoring", "source": "api.stats_hourly", "target": "ui.monitoring_dashboard", "kind": "data" },
{ "id": "e_api_hourly__stats", "source": "api.stats_hourly", "target": "ui.statistics", "kind": "data" },
{ "id": "e_api_daily__stats", "source": "api.stats_daily", "target": "ui.statistics", "kind": "data" },
{ "id": "e_api_monthly__stats", "source": "api.stats_monthly", "target": "ui.statistics", "kind": "data" },
{ "id": "e_api_review__ui", "source": "api.parent_inference_review", "target": "ui.parent_review", "kind": "data" },
{ "id": "e_api_exclusions__ui", "source": "api.parent_inference_exclusions", "target": "ui.parent_exclusion", "kind": "data" },
{ "id": "e_api_label__ui", "source": "api.parent_inference_label_sessions", "target": "ui.label_session", "kind": "data" },
{ "id": "e_api_enf_records__history", "source": "api.enforcement_records", "target": "ui.enforcement_history", "kind": "data" },
{ "id": "e_api_enf_plans__plan", "source": "api.enforcement_plans", "target": "ui.enforcement_plan", "kind": "data" },
{ "id": "e_api_vessel_analysis__detail", "source": "api.vessel_analysis", "target": "ui.vessel_detail", "kind": "data" },
{ "id": "e_api_vessel_analysis__live", "source": "api.vessel_analysis", "target": "ui.live_map", "kind": "data" },
{ "id": "e_api_vessel_analysis__gear", "source": "api.vessel_analysis", "target": "ui.gear_detection", "kind": "data" },
{ "id": "e_api_vessel_analysis__dark", "source": "api.vessel_analysis", "target": "ui.dark_vessel", "kind": "data" },
{ "id": "e_redis__ai_assistant", "source": "external.redis", "target": "ui.ai_assistant", "label": "GET context", "kind": "data" },
{ "id": "e_event_list__ack", "source": "ui.event_list", "target": "decision.event_ack", "kind": "trigger" },
{ "id": "e_event_list__resolve", "source": "ui.event_list", "target": "decision.event_resolve", "kind": "trigger" },
{ "id": "e_event_list__fp", "source": "ui.event_list", "target": "decision.event_false_positive", "kind": "trigger" },
{ "id": "e_ack__api", "source": "decision.event_ack", "target": "api.events_ack", "label": "PATCH", "kind": "trigger" },
{ "id": "e_resolve__api", "source": "decision.event_resolve", "target": "api.events_status", "label": "PATCH", "kind": "trigger" },
{ "id": "e_fp__api", "source": "decision.event_false_positive", "target": "api.events_status", "label": "PATCH", "kind": "trigger" },
{ "id": "e_ack_api__store", "source": "api.events_ack", "target": "storage.event_workflow", "label": "UPDATE", "kind": "data" },
{ "id": "e_status_api__store", "source": "api.events_status", "target": "storage.event_workflow", "label": "UPDATE", "kind": "data" },
{ "id": "e_parent_review__confirm", "source": "ui.parent_review", "target": "decision.parent_confirm", "kind": "trigger" },
{ "id": "e_parent_review__reject", "source": "ui.parent_review", "target": "decision.parent_reject", "kind": "trigger" },
{ "id": "e_confirm__api", "source": "decision.parent_confirm", "target": "api.parent_inference_confirm", "label": "POST", "kind": "trigger" },
{ "id": "e_reject__api", "source": "decision.parent_reject", "target": "api.parent_inference_confirm", "label": "POST", "kind": "trigger" },
{ "id": "e_confirm_api__store", "source": "api.parent_inference_confirm", "target": "storage.gear_group_parent_resolution", "label": "UPDATE", "kind": "data" },
{ "id": "e_exclusion_ui__decision", "source": "ui.parent_exclusion", "target": "decision.candidate_exclude", "kind": "trigger" },
{ "id": "e_exclude__api", "source": "decision.candidate_exclude", "target": "api.parent_inference_exclusions", "label": "POST", "kind": "trigger" },
{ "id": "e_exclude_api__store", "source": "api.parent_inference_exclusions", "target": "storage.gear_parent_candidate_exclusions", "label": "INSERT", "kind": "data" },
{ "id": "e_label_ui__start", "source": "ui.label_session", "target": "decision.label_session_start", "kind": "trigger" },
{ "id": "e_label_start__api", "source": "decision.label_session_start", "target": "api.parent_inference_label_sessions", "label": "POST", "kind": "trigger" },
{ "id": "e_label_api__store", "source": "api.parent_inference_label_sessions", "target": "storage.gear_parent_label_sessions", "label": "INSERT", "kind": "data" },
{ "id": "e_history_ui__register", "source": "ui.enforcement_history", "target": "decision.enforcement_register", "kind": "trigger" },
{ "id": "e_plan_ui__register", "source": "ui.enforcement_plan", "target": "decision.enforcement_register", "kind": "trigger" },
{ "id": "e_register__api", "source": "decision.enforcement_register", "target": "api.enforcement_records", "label": "POST", "kind": "trigger" },
{ "id": "e_register_api__store", "source": "api.enforcement_records", "target": "storage.enforcement_records", "label": "INSERT", "kind": "data" },
{ "id": "e_plan_api__store", "source": "api.enforcement_plans", "target": "storage.enforcement_plans", "label": "INSERT", "kind": "data" },
{ "id": "e_register__events_resolved", "source": "decision.enforcement_register", "target": "storage.prediction_events", "label": "RESOLVED 업데이트", "kind": "feedback" },
{ "id": "e_confirm__feedback_inference", "source": "decision.parent_confirm", "target": "fleet.parent_inference", "label": "다음 사이클 학습", "kind": "feedback" },
{ "id": "e_exclusions__feedback_inference", "source": "storage.gear_parent_candidate_exclusions", "target": "fleet.parent_inference", "label": "후보 필터링", "kind": "feedback" },
{ "id": "e_label__feedback_inference", "source": "storage.gear_parent_label_sessions", "target": "fleet.parent_inference", "label": "정답 라벨", "kind": "feedback" },
{ "id": "e_enforcement__feedback_results", "source": "storage.enforcement_records", "target": "storage.vessel_analysis_results", "label": "검증 라벨", "kind": "feedback" },
{ "id": "e_fp__feedback_classifier", "source": "decision.event_false_positive", "target": "output.violation_classifier", "label": "오탐 학습", "kind": "feedback" }
]