커밋 그래프

49 커밋

작성자 SHA1 메시지 날짜
f589cb0f94 fix(frontend): 카탈로그 배지 테마 분리 + 단속 조치 가독성 수정
변경:
- badgeVariants 8 intent 모두 라이트/다크 팔레트 분리
  - 다크: 밝은 솔리드 배경(-400) + slate-900 글자 + 강한 보더(-600)
  - 라이트: 파스텔 배경(-100) + 진한 글자(-900) + 소프트 보더(-300)
  - base에서 text-on-bright 제거 (intent별로 관리)
- classes 기반 카탈로그 4종에 dark: 변형 추가로 라이트 모드 대응:
  - eventStatuses: bg-red-100 text-red-800 dark:bg-red-500/20 dark:text-red-400
  - enforcementResults: 동일 패턴 (red/purple/yellow/green)
  - patrolStatuses: border 포함 (7 상태)
  - enforcementActions: classes 필드 신규 추가 (기존에 없어서 fallback grey로 떨어져
    라이트 모드에서 글자 안 보이던 원인)
- CatalogSection fallback classes도 dark: 변형 추가 (안전장치)
- enforcementActions에 getEnforcementActionClasses() 헬퍼 신규

빌드 검증:
- tsc , vite build 
- CSS 확인: .dark\:bg-red-400:is(.dark *) 컴파일 정상
2026-04-08 11:23:38 +09:00
e0b51efc54 feat(frontend): 디자인 시스템 쇼케이스 페이지 + 신규 공통 컴포넌트
쇼케이스 (/design-system.html):
- 별도 Vite entry (System Flow 패턴 재사용, 메인 SPA 분리)
- 10개 섹션: Intro / Token / Typography / Badge / Button / Form /
  Card / Layout / Catalog (19+) / Guide
- 추적 ID 체계 (TRK-CATEGORY-SLUG):
  - hover 시 툴팁 + "ID 복사 모드"에서 클릭 시 클립보드 복사
  - URL hash 딥링크 (#trk=TRK-BADGE-critical-sm) 스크롤+하이라이트
  - 산출문서/논의에서 특정 변형 정확히 참조 가능
- Dark/Light 테마 토글로 양쪽 시각 검증

신규 공통 컴포넌트:
- Button (@shared/components/ui/button.tsx)
  - 5 variant × 3 size = 15 변형
  - primary/secondary/ghost/outline/destructive × sm/md/lg
- Input / Select / Textarea / Checkbox / Radio
  - Input · Select 공통 inputVariants 공유 (sm/md/lg × default/error/success)
- PageContainer / PageHeader / Section (shared/components/layout/)
  - PageContainer: size sm/md/lg + fullBleed (지도/풀화면 예외)
  - PageHeader: title + description + icon + demo 배지 + actions 슬롯
  - Section: Card + CardHeader + CardTitle + CardContent 단축

variants.ts 확장:
- buttonVariants / inputVariants / pageContainerVariants CVA 정의
- Button/Input/Select는 variants.ts에서 import하여 fast-refresh 경고 회피

빌드 검증 완료:
- TypeScript 타입 체크 통과
- ESLint 통과 (경고 0)
- vite build: designSystem-*.js 54KB (메인 SPA와 분리)

이 쇼케이스가 확정된 후 실제 40+ 페이지 마이그레이션 진행 예정.
2026-04-08 11:09:36 +09:00
a07b7d9ba5 docs: 릴리즈 노트 갱신 (UI 카탈로그 시스템) 2026-04-08 10:55:09 +09:00
a07c745cbc feat(frontend): 40+ 페이지 Badge/시맨틱 토큰 마이그레이션
- 모든 feature 페이지의 Badge className 패턴을 intent/size prop으로 변환
- 컬러풀 액션 버튼 (bg-*-500/600/700 + text-heading) -> text-on-vivid
- 검색/필터 버튼 배경 bg-blue-400 + text-on-bright (밝은 배경 위 검정)
- ROLE_COLORS 4곳 중복 제거 (MainLayout/UserRoleAssignDialog/
  PermissionsPanel/AccessControl) -> getRoleBadgeStyle 공통 호출
- PermissionsPanel 역할 생성/수정에 ColorPicker 통합
- MainLayout: PagePagination + scroll page state 제거 (데이터 페이지네이션 혼동)
- Dashboard RiskBar 단위 버그 수정 (0~100 정수 처리)
- ReportManagement, TransferDetection p-5 space-y-4 padding 복구
- EnforcementHistory 그리드 minmax 적용으로 컬럼 잘림 해소
- timeline 시간 formatDateTime 적용 (ISO T 구분자 처리)
- 각 feature 페이지가 공통 카탈로그 API (getXxxIntent/Label/Classes) 사용
2026-04-08 10:53:58 +09:00
5812d9dea3 feat(frontend): UI 공통 인프라 + 19개 분류 카탈로그 구축
- cn() 유틸 신규 (clsx + tailwind-merge, 시맨틱 토큰 classGroup 등록)
- theme.css @layer utilities로 직접 정의 (Tailwind v4 복합 이름 매핑 실패 대응):
  text-heading/label/hint/on-vivid/on-bright, bg-surface-raised/overlay
- badgeVariants (CVA) 재구축: 8 intent x 4 size, rem 기반, !important 제거
- Badge 컴포넌트가 cn(badgeVariants, className)로 override 허용
- DataTable width 의미 변경: 고정 -> 선호 최소 너비 (minWidth), truncate + title 툴팁
- dateFormat.ts sv-SE 로케일로 YYYY-MM-DD HH:mm:ss 일관된 KST 출력
- ColorPicker 신규 (팔레트 + native color + hex 입력)
- shared/constants/ 19개 카탈로그: violation/alert/event/enforcement/patrol/
  engine/userRole/device/parentResolution/modelDeployment/gearGroup/darkVessel/
  httpStatus/userAccount/loginResult/permission/vesselAnalysis/connection/trainingZone
  + kpiUiMap. 백엔드 enum/code_master 기반 SSOT
- i18n ko/en common.json에 카테고리 섹션 추가
- adminApi.fetchRoles()가 updateRoleColorCache 자동 호출
- 공통 컴포넌트 (ExcelExport/NotificationBanner/Pagination/SaveButton) 시맨틱 토큰 적용
2026-04-08 10:53:40 +09:00
20d6743c17 feat(backend): Role.colorHex 추가 + V017 migration
- auth_role.color_hex VARCHAR(7) 컬럼 추가 (Flyway V017)
- 빌트인 5개 역할 기본 색상 시드 (ADMIN/OPERATOR/ANALYST/FIELD/VIEWER)
- Role 엔티티 + RoleCreate/UpdateRequest DTO + RoleManagementService
- PermTreeController 응답에 colorHex 필드 포함
2026-04-08 10:52:36 +09:00
7ed07093db Merge pull request 'docs: 프로젝트 문서 최신화 (2026-04-08)' (#16) from docs/project-status-2026-04-08 into develop 2026-04-08 07:11:07 +09:00
7f35103c60 docs: 프로젝트 문서 최신화 (2026-04-08)
## 메모리 갱신 (Claude 내부)
- project-snapshot.md: 48테이블, V001~V016, prediction e2e 정상, System Flow 뷰어, 데모계정 5종
- project-history.md: 2026-04-07~08 릴리즈 이력 요약 (MR #3~#15)
- next-task: 1순위를 UI/표기 다듬기로 전환
- api-types: /api/stats/hourly + V014~V016 보조 테이블 추가
- debugging: 최근 해결된 11개 이슈 패턴 정리
- 구버전 참고 파일 정리 (data-analysis, refactoring-decisions)

## 리포지토리 문서
- docs/RELEASE-NOTES.md: Unreleased 섹션에 prediction e2e 수정, System Flow 포커스 모드,
  hourly API, V014~V016, mock 정리, KST 통일, DemoQuickLogin hostname 등 추가
- CLAUDE.md: database/ 설명 V001~V016, 48 테이블로 갱신

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 07:10:22 +09:00
930fbfc841 Merge pull request 'fix: DemoQuickLogin hostname 기반 노출' (#14) from feature/demo-login-hostname into develop 2026-04-08 06:59:02 +09:00
666d6e88c8 fix: DemoQuickLogin 노출 조건에 hostname 기반 판정 추가
Gitea CI 빌드에 .env 파일이 포함되지 않아 VITE_SHOW_DEMO_LOGIN이
주입되지 않는 문제 대응. 허용된 호스트에서는 환경변수 없이도 데모 퀵로그인 표시.

허용 호스트:
- localhost / 127.0.0.1 (로컬 개발)
- kcg-ai-monitoring.gc-si.dev (현재 데모 운영)

실운영 호스트로 전환 시 DEMO_ALLOWED_HOSTS에서 제거 필요.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 06:58:39 +09:00
1ff8a6ac7f Merge pull request 'fix: prediction e2e — Decimal/violation/KPI/stats/parent workflow 5건 수정' (#12) from feature/prediction-e2e-fixes into develop 2026-04-08 06:48:19 +09:00
da37a00b8e fix: prediction 5가지 이슈 수정 — 모든 파이프라인 정상 동작
## 이슈 1: gear_correlation Decimal → float TypeError
- prediction/algorithms/gear_correlation.py:785
- _load_all_scores()가 NUMERIC 컬럼을 Decimal로 읽어 float 상수와 연산 시 실패
- float() 명시 변환으로 수정
- 효과: gear correlation 24,474 raw metrics + 3,966 scores 정상 기록

## 이슈 2: violation_classifier classified=0 문제
- prediction/output/violation_classifier.py
- result.get('id')는 AnalysisResult에 없어 항상 None → 모든 UPDATE 건너뜀
- 존재하지 않는 permit_status/gear_judgment 필드에 의존
- (mmsi, analyzed_at) 기준 UPDATE로 변경
- 중국 선박(412/413*) + EEZ 진입은 permit 없어도 EEZ_VIOLATION 판정
- 효과: classified=0 → classified=4~6/cycle

## 이슈 3: kpi_writer 모두 0 (tracking_active 외)
- prediction/output/kpi_writer.py:27
- date.today() + timezone.utc 혼용 → 현재 시각이 UTC로는 아직 '어제'라 '오늘 >= today_start' 쿼리가 0 반환
- KST 기준으로 today_start 계산
- 효과: realtime_detection 0 → 7,107, illegal_transship 0 → 5,033

## 이슈 4: stats_daily 오늘 0건
- prediction/output/stats_aggregator.py:96, 194
- aggregate_daily/monthly가 UTC 경계 사용
- KST 기준 자정으로 수정
- 효과: 2026-04-08 detections 0 → 543,656, events 0 → 5,253

## 이슈 5: parent workflow 테이블 누락 컬럼 (V005 ↔ prediction 불일치)
V016 마이그레이션으로 일괄 추가:
- gear_parent_label_sessions: label_parent_name, normalized_parent_name,
  duration_days, actor, comment, metadata, updated_at 등 8개 컬럼
- gear_group_parent_resolution: parent_name, normalized_parent_name,
  selected_parent_name, confidence, decision_source, top_score, second_score,
  score_margin, stable_cycles, evidence_summary, episode_id, continuity_*,
  prior_bonus_total, last_evaluated_at, last_promoted_at 등 17개 컬럼
- gear_parent_candidate_exclusions: normalized_parent_name, reason_type,
  duration_days, metadata, updated_at, active_from, active_until +
  candidate_mmsi GENERATED ALWAYS AS (excluded_mmsi) 별칭
- gear_group_parent_candidate_snapshots: parent_name

효과: gear parent inference: 925 groups, 301 direct-match, 1329 candidates,
      188 review-required, 925 episode-snapshots 기록 — 전체 모선 워크플로우 정상

## 검증 결과 (e2e)

- analysis cycle: 6,824 vessels, 112초/cycle 정상
- vessel_analysis_results: 10분 13,650건, 총 125만건
- prediction_events: 1시간 138건, 총 12,258건
- prediction_alerts: 1시간 183건
- gear_correlation_scores: 3,966건
- gear_group_parent_resolution: 926건
- stats_hourly: 17행, stats_daily: 오늘 543,656건
- 백엔드 Flyway V016 정상 적용

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 06:47:53 +09:00
99764e7c99 Merge pull request 'feat: System Flow 뷰어 포커스 모드 + 엣지 겹침 완화' (#10) from feature/system-flow-focus into develop 2026-04-08 05:48:29 +09:00
17215be29c feat: System Flow 뷰어 — 포커스 모드 + 엣지 겹침 완화
## 포커스 모드
- 노드 선택 시 해당 노드 + 1-hop 연결된 노드만 활성
- 나머지 노드는 opacity 0.18 + grayscale, 엣지는 0.08로 dim 처리
- 상단 중앙 배지로 포커스 상태 표시 + "전체 보기 ✕" 해제 버튼
- 캔버스 빈 공간(pane) 클릭 시 포커스 해제
- 선택 노드는 스케일 1.02 + glow 효과로 강조

## 엣지 겹침 완화
- COL_WIDTH 360 → 440, ROW_HEIGHT 130 → 170 (간격 확대)
- smoothstep pathOptions.offset을 source별로 20→34→48... 분산
- 같은 노드에서 나가는 N번째 엣지는 서로 다른 경로로 라우팅
- 선택/포커스된 엣지는 zIndex 1000으로 최상단 표시

## 시각 보강
- 포커스된 엣지는 stroke #f8fafc + strokeWidth 2.8 + animated
- 비활성 엣지 라벨은 opacity 0.3, 텍스트 #475569로 어둡게
- 선택 노드 body: box-shadow + glow + scale 1.02

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 05:47:51 +09:00
d55b177dec Merge pull request 'feat: System Flow 뷰어 — 시스템 전체 데이터 흐름 시각화 (102 노드)' (#8) from feature/system-flow-viewer into develop 2026-04-07 17:11:13 +09:00
5d0bca73e1 docs: 릴리즈 노트에 System Flow 뷰어 항목 추가
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:10:46 +09:00
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
8dd86b692e Merge pull request 'fix: prediction e2e + 프론트 mock 전수 정리 + KST 통일' (#6) from feature/prediction-e2e-backend-fix into develop 2026-04-07 15:37:07 +09:00
19b1613157 feat: 프론트 전수 mock 정리 + UTC→KST 통일 + i18n 수정 + stats hourly API
## 시간 표시 KST 통일
- shared/utils/dateFormat.ts 공통 유틸 신규 (formatDateTime/formatDate/formatTime/toDateParam)
- 14개 파일에서 인라인 toLocaleString → 공통 유틸 교체

## i18n 'group.parentInference' 사이드바 미번역 수정
- ko/en common.json의 'group' 키 중복 정의를 병합
  (95행 두번째 group 객체가 35행을 덮어써서 parentInference 누락)

## Dashboard/MonitoringDashboard/Statistics 더미→실 API
- 백엔드 GET /api/stats/hourly 신규 (PredictionStatsHourly 엔티티/리포지토리)
- Dashboard: HOURLY_DETECTION/VESSEL_TYPE/AREA_RISK 하드코딩 제거 →
  getHourlyStats(24) + getDailyStats(today) 결과로 useMemo 변환
- MonitoringDashboard: TREND Math.random() 제거 → getHourlyStats 기반
  위험도 가중평균 + 경보 카운트
- Statistics: KPI_DATA 하드코딩 제거 → getKpiMetrics() 결과를 표 행으로

## Store mock 의존성 제거
- eventStore.alerts/MOCK_ALERTS 제거 (MobileService는 events에서 직접 추출)
- enforcementStore.plans 제거 (EnforcementPlan은 이미 직접 API 호출)
- transferStore + MOCK_TRANSFERS 완전 제거
  (ChinaFishing/TransferDetection은 RealTransshipSuspects 컴포넌트 사용)
- mock/events.ts, mock/enforcement.ts, mock/transfers.ts 파일 삭제

## RiskMap 랜덤 격자 제거
- generateGrid() Math.random() 제거 → 빈 배열 + 'AI 분석 데이터 수집 중' 안내
- MTIS 외부 통계 5개 탭에 [MTIS 외부 통계] 배지 추가

## 12개 mock 화면에 '데모 데이터' 노란색 배지 추가
- patrol/PatrolRoute, FleetOptimization
- admin/AdminPanel, DataHub, NoticeManagement, SystemConfig
- ai-operations/AIModelManagement, MLOpsPage
- field-ops/ShipAgent
- statistics/ReportManagement, ExternalService
- surveillance/MapControl

## 백엔드 NUMERIC precision 동기화
- PredictionKpi.deltaPct: 5,2 → 12,2
- PredictionStatsDaily/Monthly.aiAccuracyPct: 5,2 → 12,2
- (V015 마이그레이션과 동기화)

44 files changed, +346 / -787

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:36:38 +09:00
e12d1c33e2 fix: prediction e2e — 누락 테이블 12개 + 컬럼 매핑 + NUMERIC precision 통합 수정
- V014: fleet_vessels, fleet_tracking_snapshot, gear_identity_log,
  gear_correlation_scores/raw_metrics, correlation_param_models,
  group_polygon_snapshots, gear_group_episodes/episode_snapshots,
  gear_group_parent_candidate_snapshots, gear_parent_label_tracking_cycles,
  system_config 테이블 추가
- V015: 점수/비율 NUMERIC precision 일괄 확대 (score→7,4 / pct→12,2) +
  vessel_analysis_results UNIQUE(mmsi, analyzed_at) 인덱스 추가
- prediction kcgdb.py: timestamp→analyzed_at, zone→zone_code,
  is_leader→fleet_is_leader, is_transship_suspect→transship_suspect 매핑

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:00:29 +09:00
4db7874082 Merge pull request 'docs: 릴리즈 노트 정리 (2026-04-07)' (#4) from release/2026-04-07 into develop 2026-04-07 13:58:53 +09:00
49140cc8fc docs: 릴리즈 노트 정리 (2026-04-07)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:58:28 +09:00
a01cd926a7 Merge pull request 'feat: 모노레포 전환 + 백엔드 RBAC + prediction 이식 + 15화면 실데이터 연동' (#3) from feature/monorepo-backend-rbac into develop 2026-04-07 13:57:27 +09:00
69ff79d90d docs: 릴리즈 노트 업데이트
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:56:43 +09:00
19c69c72c3 chore: .env.development.example → .env.example (서버 hook .env.* 차단 대응)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:54:22 +09:00
a7f3490091 chore: .env.development → .example + pre-commit 모노레포 대응
- .env.development을 git에서 제거, .example로 대체 (서버 정책 준수)
- pre-commit hook을 frontend/ 기준으로 수정 (모노레포 구조)
- custom_pre_commit 플래그 활성화

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:52:53 +09:00
3ced9ffaaa docs: 배포 문서 보강 + CI/CD 모노레포 수정 + CLAUDE.md 배포 섹션
deploy/README.md:
- 접속 정보 섹션 추가 (URL, 데모 계정, DB)
- CI/CD 섹션: 프론트 자동(Gitea Actions), 백엔드/prediction 수동
- 서버별 실행 경로 정리 (rocky-211, redis-211)

.gitea/workflows/deploy.yml:
- 모노레포 구조 반영 (working-directory: frontend)
- paths 필터: frontend/** 변경 시만 트리거

CLAUDE.md:
- 모노레포 구조에 prediction/, deploy/, .gitea/ 추가
- 배포 환경 섹션 추가 (서버/포트/관리 방법)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:43:19 +09:00
2cb8414676 feat: 배포 환경 구성 + 로컬 프록시 서버 전환
rocky-211 백엔드 배포:
- /devdata/services/kcg-ai-monitoring/backend/ (JAR + application-prod.yml)
- systemd kcg-ai-backend.service (포트 18080)

redis-211 prediction 배포:
- /home/apps/kcg-ai-prediction/ (포트 18092)
- systemd kcg-ai-prediction.service

nginx 프록시 (rocky-211):
- /api/ → localhost:18080 (Spring Boot)
- /api/prediction/ → 192.168.1.18:18092 (prediction)
- /api/prediction-chat → SSE 프록시

로컬 개발:
- vite 프록시 기본값을 서버(kcg-ai-monitoring.gc-si.dev)로 변경
- 로컬 백엔드 사용 시: VITE_API_PROXY=http://localhost:8080

deploy/README.md: 배포 가이드 문서화

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:38:45 +09:00
6ac9184016 feat: VesselDetail + LiveMapView 실데이터 전환
VesselDetail: 인라인 mock → fetchVesselAnalysis() + vessel-permits API
  - MMSI 기반 선박 분석 데이터 + 허가 정보 + 관련 이벤트 이력
  - 알고리즘 결과 전체 표시 (risk/dark/spoofing/transship/fleet)

LiveMapView: vesselStore mock → fetchVesselAnalysis() + getEvents()
  - 위험도 TOP 100 선박 마커 (riskLevel별 색상)
  - 활성 이벤트 오버레이

EventController에 vesselMmsi 필터 파라미터 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:29:43 +09:00
cc1b1e20df feat: S4 alerts API + AIAlert/Dashboard 위험선박 실데이터 전환
백엔드:
- PredictionAlert 엔티티 + Repository
- AlertController: GET /api/alerts (페이징 + eventId 필터)

프론트:
- AIAlert: mock alerts → GET /api/alerts 실제 호출
- Dashboard 위험선박: vesselStore mock → fetchVesselAnalysis() API
  - riskScore TOP 8 선박, 다크/GPS변조/전재 배지 표시
- Dashboard 이벤트 타임라인: eventStore API 기반 동작 확인

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:09:08 +09:00
474e672683 feat: S3 prediction 신규 출력 모듈 5종 + scheduler 통합
분석 사이클 완료 후 자동 실행되는 출력 파이프라인:
- event_generator: 분석결과 → 이벤트 자동 생성 (7개 룰, 카테고리별 dedup)
- violation_classifier: 위반 유형 라벨링 (EEZ/DARK/MMSI/TRANSSHIP/GEAR/RISK)
- kpi_writer: 실시간 KPI 6개 갱신 (오늘 기준 카운트)
- stats_aggregator: hourly/daily/monthly 사전 집계 (UPSERT)
- alert_dispatcher: CRITICAL/HIGH 이벤트 자동 알림 생성

scheduler.py에 출력 모듈 통합 (분석 8단계 완료 후 실행, non-fatal)
DB 연동 테스트 통과 (alerts 8건 생성, KPI tracking_active=2)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:00:50 +09:00
e2fc355b2c feat: S2 prediction 분석 엔진 모노레포 이식
iran prediction 47개 Python 파일을 prediction/ 디렉토리로 복제:
- algorithms/ 14개 분석 알고리즘 (어구추론, 다크베셀, 스푸핑, 환적, 위험도 등)
- pipeline/ 7단계 분류 파이프라인
- cache/vessel_store (24h 슬라이딩 윈도우)
- db/ 어댑터 (snpdb 원본조회, kcgdb 결과저장)
- chat/ AI 채팅 (Ollama, 후순위)
- data/ 정적 데이터 (기선, 특정어업수역 GeoJSON)

config.py를 kcgaidb로 재구성 (DB명, 사용자, 비밀번호)
DB 연결 검증 완료 (kcgaidb 37개 테이블 접근 확인)
Makefile에 dev-prediction / dev-all 타겟 추가
CLAUDE.md에 prediction 섹션 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:56:51 +09:00
c17d190e1d feat: S5 프론트 나머지 화면 실데이터 전환 — 탐지/함정/단속계획
탐지 화면 3개:
- GearDetection: gearStore 더미 → fetchGroups() API (GEAR_IN/OUT_ZONE)
- DarkVesselDetection: vesselStore 더미 → fetchVesselAnalysis() + filterDarkVessels()
  - 패턴 자동 분류 (완전차단/장기소실/MMSI변조/간헐송출)
- ChinaFishing: inline 더미 → fetchVesselAnalysis() + mmsi 412* 필터
  - 센서 카운터 동적 계산, 위험도 분포 도넛 차트

함정/단속계획:
- patrol.ts: 스텁 → GET /api/patrol-ships 실제 호출
- patrolStore: API 기반 (routes/scenarios는 mock 유지)
- EnforcementPlan: GET /api/enforcement/plans 연결

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:46:08 +09:00
4e6ac8645a feat: S5 프론트 실데이터 전환 — EventList/Statistics/EnforcementHistory/Dashboard KPI
이벤트 목록 (EventList):
- eventStore를 GET /api/events 호출로 전환
- 서버 필터링 (level/status/category), 페이지네이션
- 상태 배지 (NEW/ACK/IN_PROGRESS/RESOLVED/FALSE_POSITIVE)
- getEventStats() 기반 KPI 카드

단속 이력 (EnforcementHistory):
- 신규 services/enforcement.ts (GET/POST /enforcement/records, /plans)
- enforcementStore를 API 기반으로 전환
- KPI 카드 (총단속/처벌/AI일치/오탐) 클라이언트 계산

통계 (Statistics):
- kpi.ts를 GET /api/stats/kpi, /stats/monthly 실제 호출로 전환
- toMonthlyTrend/toViolationTypes 변환 헬퍼 추가
- BarChart/AreaChart 기존 구조 유지

대시보드 KPI:
- kpiStore를 API 기반으로 전환 (getKpiMetrics + getMonthlyStats)
- Dashboard KPI_UI_MAP에 kpiKey 기반 매핑 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:14:53 +09:00
b70ef399b5 fix: prediction_stats_monthly.stat_month CHAR(7) → DATE 타입 변경
날짜 기반 정렬/범위쿼리/집계함수 활용을 위해 VARCHAR(7)→DATE로 변환.
매월 1일(2026-04-01)로 저장. 엔티티/Repository/Controller 파라미터 동시 수정.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:05:04 +09:00
91deb3ae55 feat: S1 백엔드 API — 이벤트/통계/단속/마스터 데이터 CRUD
이벤트 허브 (domain/event/):
- PredictionEvent/EventWorkflow 엔티티 + JPA Specification 필터
- EventController: 목록/상세/이력/상태변경/통계 6개 엔드포인트
- 상태 변경 시 EventWorkflow 자동 기록 (감사 추적)

통계/KPI (domain/stats/):
- PredictionKpi/StatsMonthly/StatsDaily 엔티티
- StatsController: KPI/월별/일별 통계 3개 엔드포인트

단속 이력/계획 (domain/enforcement/):
- EnforcementRecord/Plan 엔티티 + UID 자동생성
- EnforcementController: 단속이력/계획 CRUD 6개 엔드포인트
- 단속 등록 시 이벤트 상태 자동 RESOLVED 연동

마스터 데이터 (master/):
- CodeMaster/GearType/PatrolShip/VesselPermit 엔티티 + Repository
- MasterDataController: 코드/어구유형/함정/선박허가 10개 엔드포인트

총 25개 신규 엔드포인트, 98개 Java 소스 파일 컴파일 성공.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:02:26 +09:00
883b347359 feat: S1 마스터 데이터 + prediction 기반 DB 스키마 (V008~V013)
prediction 모노레포 이관을 위한 DB 기반 구축:
- V008: 계층형 code_master (12그룹 72코드, 위반유형/이벤트/단속/허가/함정 등)
- V009: gear_type_master 어구 유형 6종 (분류 룰 + 합법성 기준)
- V010: zone_polygon_master PostGIS 해역 폴리곤 (8개 주요 해역)
- V011: vessel_permit_master + patrol_ship_master + fleet_companies 시드
- V012: vessel_analysis_results(파티션) + prediction_events 허브 + 알림 + 통계 + KPI
- V013: enforcement_records/plans + patrol_assignments + ai_model 메타
- Hibernate Spatial 의존성 추가 (PostGIS 지원)
- 프론트엔드 더미 데이터 기반 시드 (이벤트 15건, 단속 6건, 계획 5건, 월별통계 7개월)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 11:49:26 +09:00
f545aeafac fix: 권한 트리 UX 개선 + 라벨 사이드바 일치 + EXPORT 가드
PermissionsPanel UI 수정:
- 같은 노드의 effective READ가 거부되면 C/U/D/E도 forced-denied
  (READ가 안 되면 그 페이지 자체에 접근 못 하므로 다른 작업도 의미 없음)
  → 사용자가 Read를 N으로 바꾸는 즉시 같은 행의 CUDE도 회색 비활성

DataTable EXPORT 권한 가드:
- exportResource prop 추가
- useAuth().hasPermission(resource, 'EXPORT')로 export 버튼 표시 여부 결정
- AccessControl의 사용자 관리 / 감사 로그 DataTable에 적용
  - exportResource="admin:user-management"
  - exportResource="admin:audit-logs"

Operation 의미 명확화:
- ParentExclusion release 엔드포인트를 UPDATE → DELETE 로 재분류
  (제외 항목을 "삭제(해제)"하는 의미가 더 정확)

V007 마이그레이션: 권한 트리 명칭을 사이드바 i18n 라벨과 일치
- Level 0 13개 + Level 1 32개 노드의 rsrc_nm을 nav.* / group.* 라벨에 맞춤
- 예: "어구탐지" → "어구 탐지", "Dark Vessel" → "다크베셀 탐지"
- 권한 관리 트리를 운영자가 사이드바와 동일한 명칭으로 이해 가능

API의 RCUDE 적용 현황 (참고):
- READ 19건, UPDATE 8건, CREATE 4건, DELETE 1→2건
- EXPORT는 백엔드 엔드포인트 별도 없음 → 프론트 EXPORT 가드로 처리
- 향후 백엔드 CSV/Excel 생성 API 추가 시 EXPORT operation으로 가드

검증:
- V007 마이그레이션 자동 적용 + Started in 3.272s
- Level 0 13개 모두 사이드바 라벨로 변경됨 확인
- 프론트 빌드 통과 (599ms)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 10:33:29 +09:00
95ca1018b5 feat: Phase 6-8 - iran 백엔드 실연결 + 시스템 상태 + AI 채팅 기반
Phase 6: iran 백엔드 실연결 + 화면 연동
- application.yml: app.iran-backend.base-url=https://kcg.gc-si.dev
- IranBackendClient: RestClient 확장 (Accept JSON header, getAs<T>)
- VesselAnalysisProxyController: HYBRID 합성 로직 추가
  - GET /api/vessel-analysis: stats + 7423건 분석 결과 통과
  - GET /api/vessel-analysis/groups: 476건 그룹 + 자체 DB resolution 합성
  - GET /api/vessel-analysis/groups/{key}/detail
  - GET /api/vessel-analysis/groups/{key}/correlations
  - 권한: detection / detection:gear-detection (READ)
- 프론트 services/vesselAnalysisApi.ts: 타입 + 필터 헬퍼
  (filterDarkVessels, filterSpoofingVessels, filterTransshipSuspects)
- features/detection/RealGearGroups.tsx: 어구/선단 그룹 실시간 표시
  (FLEET/GEAR_IN_ZONE/GEAR_OUT_ZONE 필터, 통계 5종, 운영자 결정 합성 표시)
- features/detection/RealVesselAnalysis.tsx: 분석 결과 모드별 렌더
  - mode='dark' / 'spoofing' / 'transship' / 'all'
  - 위험도순 정렬 + 6개 통계 카드 + 해역/Dark/Spoofing/전재 표시
- 화면 연동:
  - GearDetection → RealGearGroups 추가
  - DarkVesselDetection → RealDarkVessels + RealSpoofingVessels
  - ChinaFishing(dashboard) → RealAllVessels
  - TransferDetection → RealTransshipSuspects

Phase 7: 시스템 상태 대시보드
- features/monitoring/SystemStatusPanel.tsx
  - 3개 서비스 카드: KCG Backend / iran 백엔드 / Prediction
  - 위험도 분포 (CRITICAL/HIGH/MEDIUM/LOW) 4개 박스
  - 30초 자동 폴링
- MonitoringDashboard 최상단에 SystemStatusPanel 추가

Phase 8: AI 채팅 기반 (SSE는 Phase 9 인증 후)
- 프론트 services/chatApi.ts: sendChatMessage (graceful fallback)
- 백엔드 PredictionProxyController.chat 추가
  - POST /api/prediction/chat
  - 권한: ai-operations:ai-assistant (READ)
  - 현재 stub 응답 (iran chat 인증 토큰 필요)
- AIAssistant 페이지에 백엔드 호출 통합
  (handleSend → sendChatMessage → 응답 표시 + graceful 메시지)

검증:
- 백엔드 컴파일/기동 성공 (Started in 5.2s)
- iran 프록시: 471개 그룹, 7423건 분석 결과 정상 통과
- 프론트 빌드 통과 (502ms)
- E2E 시나리오:
  - admin 로그인 → /api/vessel-analysis/groups → 476건 + serviceAvailable=true
  - /api/prediction/chat → stub 응답 (Phase 9 안내)

설계 원칙:
- iran 백엔드 미연결 시 graceful degradation (serviceAvailable=false + 빈 데이터)
- HYBRID 합성: prediction 후보 + 자체 DB의 운영자 결정을 백엔드에서 조합
- 향후 iran 인증 토큰 통과 후 SSE 채팅 활성화

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 10:22:04 +09:00
febfb2cbe8 feat: Phase 5 - 권한 관리 UI 고도화 (트리 RBAC PermissionsPanel)
버그 수정:
- AccessControl 무한 새로고침 (loadRoles의 userStats 의존성 → setUserStats 호출 → 무한 루프)
  loadRoles에서 항상 fetchUserStats를 같이 호출하도록 변경

백엔드 API 추가:
- RoleManagementService (역할/권한 매트릭스 CRUD)
  - createRole / updateRole / deleteRole (built-in 보호)
  - updatePermissions (Y/N upsert + null 시 명시 권한 제거)
  - assignUserRoles (전체 교체 방식, 권한 캐시 evict)
  - 모든 액션에 @Auditable 자동 기록
- PermTreeController 확장:
  - POST /api/roles (admin:role-management:CREATE)
  - PUT /api/roles/{sn} (admin:role-management:UPDATE)
  - DELETE /api/roles/{sn} (admin:role-management:DELETE)
  - PUT /api/roles/{sn}/permissions (admin:permission-management:UPDATE)
  - PUT /api/admin/users/{id}/roles (admin:user-management:UPDATE)
- DTO: RoleCreateRequest, RoleUpdateRequest, PermissionUpdateRequest, UserRoleAssignRequest
- GlobalExceptionHandler:
  - IllegalArgumentException → 400 BAD_REQUEST
  - IllegalStateException → 409 CONFLICT
  - AccessDeniedException → 403 FORBIDDEN

프론트엔드:
- lib/permission/permResolver.ts (TypeScript 미러)
  - resolveSingleRoleEffective: 백엔드 PermResolver와 동일 알고리즘
  - 4가지 셀 상태 계산 (explicit-granted/inherited-granted/explicit-denied/forced-denied)
- PermissionsPanel.tsx (트리 + R/C/U/D/E 매트릭스)
  - 좌측: 역할 목록 + 신규 생성 + 삭제 (built-in 보호)
  - 우측: 트리 표 + 셀 클릭 (Y → N → 미지정 순환)
  - 부모 READ 게이팅 시각화 (강제 거부 회색 비활성)
  - 변경된 셀만 일괄 저장 (dirty 추적)
- UserRoleAssignDialog.tsx
  - 사용자에게 역할 다중 선택 배정 (체크박스)
- adminApi.ts 확장: createRole/updateRole/deleteRole/updateRolePermissions/assignUserRoles
- AccessControl.tsx 갱신:
  - 역할 관리 탭 → PermissionsPanel 통합
  - 사용자 관리 탭 → 역할 배정 버튼 추가 (UserCog 아이콘)

검증:
- 역할 생성 → TESTROLE 6번으로 추가
- 권한 매트릭스 갱신 → dashboard/monitoring READ 부여 (changed: 2)
- 역할 삭제 → built-in이 아니면 OK
- built-in ADMIN 삭제 시도 → 400 BAD_REQUEST (BUILTIN_ROLE_CANNOT_DELETE)
- viewer에게 OPERATOR + ANALYST 다중 배정 → roles=[OPERATOR, ANALYST]
  → 재로그인 시 detection READ 등 자동 상속 확인
- 권한 캐시 evictAllPermissions 즉시 반영
- 프론트 빌드 통과 (533ms)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 10:11:27 +09:00
fc1a686700 feat: 시스템 관리 페이지 백엔드 연결 + 메트릭 카드
백엔드 API 추가:
- UserManagementController (admin:user-management)
  - GET /api/admin/users : 사용자 목록 + 역할 코드
  - GET /api/admin/users/stats : 상태별/역할별/인증방식별 카운트
  - POST /api/admin/users/{id}/unlock : 잠금 해제 (@Auditable USER_UNLOCK)
  - PUT /api/admin/users/{id}/status : 상태 변경 (@Auditable USER_STATUS_CHANGE)
  - 권한 캐시 evict 자동 호출
- AdminStatsController (admin:audit-logs/access-logs/login-history READ)
  - GET /api/admin/stats/audit : 전체/24시간/실패/액션별/시간별 통계
  - GET /api/admin/stats/access : 전체/24시간/4xx/5xx/평균응답/인기경로
  - GET /api/admin/stats/login : 성공률/사용자별/일별 추세

프론트엔드 연결:
- adminApi.ts 확장: AdminUser/UserStats/AuditStats/AccessStats/LoginStats
  타입 정의 + 사용자/통계 fetch 함수
- AccessControl.tsx (시스템 관리 > 권한 관리):
  - 4개 탭 모두 백엔드 연결
  - 역할 관리: GET /api/roles + 사용자별 카운트 표시
  - 사용자 관리: GET /api/admin/users + DataTable + 잠금 해제 버튼
    + 통계 카드 4개 (총/활성/잠금/비활성)
  - 감사 로그: GET /api/admin/audit-logs + GET /api/admin/stats/audit
    + 액션별 분포 Badge + 통계 카드
  - 보안 정책: 실제 백엔드 동작과 일치하도록 갱신
- AuditLogs.tsx: 메트릭 카드 4개 + 액션별 분포
- AccessLogs.tsx: 메트릭 카드 5개 (전체/24시간/4xx/5xx/평균) + Top 10 경로 테이블
- LoginHistoryView.tsx: 메트릭 카드 5개 + 사용자별 + 일별 추세

검증:
- /api/admin/users → 5명 (admin/operator/analyst/field/viewer)
- /api/admin/users/stats → byRole, byStatus, byProvider 카운트
- /api/admin/stats/audit → total 15, 액션 6종, hourly 추세
- /api/admin/stats/login → success 80%, byUser top, daily 추세
- 프론트엔드 빌드 통과 (493ms)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:57:59 +09:00
bae2f33b86 feat: Phase 4 - 모선 워크플로우 + 관리자 화면 + 권한 라우트 가드
Phase 4-1: 운영자 워크플로우 백엔드 (자체 DB)
- ParentResolution / ParentReviewLog / CandidateExclusion / LabelSession 엔티티
- Repository 4종 + DTO 5종
- ParentInferenceWorkflowService (HYBRID 패턴):
  - review (CONFIRM/REJECT/RESET) - parent-inference-workflow:parent-review (UPDATE)
  - excludeForGroup - parent-inference-workflow:parent-exclusion (CREATE)
  - excludeGlobal - parent-inference-workflow:exclusion-management (CREATE) [admin]
  - releaseExclusion (UPDATE)
  - createLabelSession / cancelLabelSession (CREATE/UPDATE)
- ParentInferenceWorkflowController: @RequirePermission으로 권한 강제
- 모든 액션에 @Auditable AOP → audit_log + review_log 동시 기록

Phase 4-2: PermTreeController + AdminLogController
- GET /api/perm-tree (모든 사용자) - 메뉴/사이드바 구성용
- GET /api/roles (admin:role-management) - 역할+권한 매트릭스
- GET /api/admin/audit-logs / access-logs / login-history

Phase 4-3: iran 백엔드 프록시 (stub)
- IranBackendClient: RestClient 기반, 호출 실패 시 null 반환 (graceful)
- VesselAnalysisProxyController: serviceAvailable=false 응답
- PredictionProxyController: DISCONNECTED 응답
- Phase 5에서 iran 백엔드 실 연결 시 코드 변경 최소

Phase 4-4: 프론트엔드 services
- parentInferenceApi.ts: 모선 워크플로우 22개 함수
- adminApi.ts: 감사로그/접근이력/로그인이력/권한트리/역할 조회

Phase 4-5: 사이드바 권한 필터링 + ProtectedRoute 권한 가드
- AuthContext.PATH_TO_RESOURCE에 신규 경로 매핑 추가
- ProtectedRoute에 resource/operation prop 추가
  → 권한 거부 시 403 페이지 표시
- 모든 라우트에 권한 리소스 명시
- MainLayout 사이드바: parent-inference-workflow + admin 로그 메뉴 추가
- 사이드바 hasAccess 필터링 (이전부터 구현됨, 신규 메뉴에도 자동 적용)

Phase 4-6: 신규 페이지 3종
- ParentReview.tsx: 모선 확정/거부/리셋 + 신규 등록 폼
- ParentExclusion.tsx: GROUP/GLOBAL 제외 등록 + 해제
- LabelSession.tsx: 학습 세션 생성/취소
- AuditLogs.tsx: 감사 로그 조회
- AccessLogs.tsx: 접근 이력 조회
- LoginHistoryView.tsx: 로그인 이력 조회

Phase 4-7: i18n 키 + 라우터 등록
- 한국어/영어 nav.* + group.* 키 추가
- App.tsx에 12개 신규 라우트 등록 + 권한 가드 적용

Phase 4-8: 검증 완료
- 백엔드 컴파일/기동 성공
- 프론트엔드 빌드 성공 (475ms)
- E2E 시나리오:
  - operator 로그인 → CONFIRM 확정 → MANUAL_CONFIRMED 갱신
  - operator GROUP 제외 → 성공
  - operator GLOBAL 제외 → 403 FORBIDDEN (권한 없음)
  - operator 학습 세션 생성 → ACTIVE
  - admin GLOBAL 제외 → 성공
  - 감사 로그 자동 기록: REVIEW_PARENT/EXCLUDE_CANDIDATE_GROUP/
    LABEL_PARENT_CREATE/EXCLUDE_CANDIDATE_GLOBAL 등 14건
  - 권한 트리 RBAC + AOP 정상 동작 확인

설계 핵심:
- 운영자 의사결정만 자체 DB에 저장 (HYBRID)
- iran 백엔드 데이터는 향후 Phase 5에서 합쳐서 표시
- @RequirePermission + @Auditable로 모든 액션 권한 + 감사 자동화
- 데모 계정으로 완전한 워크플로우 시연 가능

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:44:43 +09:00
b0c9a9fffb feat: Phase 3 - 자체 인증 + 트리 기반 RBAC + 감사로그 + 데모 계정
Phase 3-1~10: 백엔드
- pom.xml에 spring-boot-starter-aop 추가
- JPA 엔티티 12종 + Repository 9종
  (User/LoginHistory/Role/UserRole/PermTree/Perm/AuditLog/AccessLog 등)
- PermResolver: wing 프로젝트의 permResolver.ts를 Java로 이식
  - 트리 BFS + 부모 READ 게이팅 + 다중 역할 OR 합집합 + 부모 fallback
- PermissionService: Caffeine 캐싱 (TTL 10분)
- JwtService + JwtAuthFilter (HttpOnly 쿠키 + Authorization 헤더 fallback)
- AuthProvider 인터페이스 + PasswordAuthProvider (BCrypt + 5회 잠금)
  - REQUIRES_NEW + noRollbackFor로 fail_cnt 증가 보존
- AuthService + LoginAuditWriter (REQUIRES_NEW로 실패 기록 보존)
- AuthController: /api/auth/login, /logout, /me
- @RequirePermission 어노테이션 + PermissionAspect (메서드 권한 체크)
- @Auditable 어노테이션 + AuditAspect (의사결정 자동 기록)
- AccessLogFilter: 모든 HTTP 요청 비동기 기록 (BlockingQueue)
- SecurityConfig 본격 도입 (CORS + JWT 필터 + 401/403 핸들러)

Phase 3-10: 데모 계정
- V006__demo_accounts.sql: 5개 데모 계정 (admin/operator/analyst/field/viewer)
  + 역할 매핑 (PLACEHOLDER 해시)
- AccountSeeder.java: 시동 시 BCrypt 해시 시드 (PLACEHOLDER만 갱신)
- 데모 계정도 실제 권한, 로그인 이력, 감사로그 기록 대상

Phase 3-11: 백엔드 검증 완료
- admin/operator/viewer 로그인 성공
- 권한 매트릭스: ADMIN(49), OPERATOR(40), VIEWER(35)
- 트리 상속 검증: detection READ → 자식 4개 자동 상속
- 잘못된 비밀번호 → fail_cnt 증가 + login_hist FAILED 기록
- 정상 로그인 → fail_cnt 0 초기화
- 모든 요청 access_log에 비동기 기록

V001/V002: CHAR(1) → VARCHAR(1) 변경 (Hibernate validate 호환성)

Phase 3-12: 프론트엔드 연동
- services/authApi.ts: 백엔드 호출 클라이언트 (login/logout/me)
- AuthContext.tsx: 백엔드 API 통합 + 트리 기반 hasPermission
  + 부모 fallback (예: detection:gear-detection 미등록 시 detection 검사)
  + 30분 세션 타임아웃 유지
- DemoQuickLogin.tsx: 데모 퀵로그인 컴포넌트 분리
  + isDemoLoginEnabled() = VITE_SHOW_DEMO_LOGIN === 'true'
  + 데모 클릭 시에도 정상 백엔드 인증 플로우 사용
- LoginPage.tsx: 백엔드 인증 호출 + DemoQuickLogin 통합
  + 에러 메시지 한국어 변환 (WRONG_PASSWORD:N, ACCOUNT_LOCKED 등)
  + GPKI/SSO 탭은 disabled (Phase 9 도입 예정)
- frontend/.env.development: VITE_SHOW_DEMO_LOGIN=true
- frontend/.env.production: VITE_SHOW_DEMO_LOGIN=true (현재 단계)
- .gitignore에 frontend/.env.{development,production} 예외 추가

설계 핵심:
- 데모 계정은 백엔드 DB에 실제 권한 부여 + 로그인/감사 기록 대상
- DemoQuickLogin 컴포넌트는 환경변수로 토글 가능하도록 구조 분리
- 향후 운영 배포 시 .env.production만 false로 변경하면 데모 영역 숨김

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:29:52 +09:00
04dfdf2d36 feat: Phase 2 - Spring Boot 백엔드 + DB 마이그레이션 초기화
Phase 2-1: PostgreSQL DB 생성
- 211.208.115.83:5432에 kcgaidb 데이터베이스 생성
- kcg-app 사용자 + kcg 스키마 생성

Phase 2-2: Spring Boot 3.5.7 + Java 21 프로젝트
- gc.mda.kcg.KcgAiApplication 메인 클래스
- 의존성: web, security, data-jpa, validation, postgresql,
  flyway, actuator, cache, lombok, caffeine, jjwt(0.12.6)
- Maven Wrapper 포함, .sdkmanrc로 Java 21 고정

Phase 2-3: application.yml
- DataSource: 211.208.115.83/kcgaidb (kcg-app)
- JPA: ddl-auto=validate, default_schema=kcg
- Flyway: classpath:db/migration, schema=kcg
- Caffeine 캐시 (permissions, users)
- prediction/iran-backend/cors/jwt 커스텀 설정
- application-local.yml (로컬 디버깅용)

Phase 2-4: Flyway 마이그레이션 V001~V005
- V001 auth_init: auth_org, auth_user, auth_role,
  auth_user_role, auth_login_hist (pgcrypto 확장 포함)
- V002 perm_tree: auth_perm_tree, auth_perm, auth_setting
  (wing 패턴의 트리 기반 RBAC)
- V003 perm_seed: 5개 역할(ADMIN/OPERATOR/ANALYST/VIEWER/FIELD)
  + 13개 Level 0 탭 + 36개 Level 1 패널 (총 49개 리소스)
  + 역할별 권한 매트릭스 일괄 INSERT
- V004 access_logs: auth_audit_log, auth_access_log
- V005 parent_workflow: gear_group_parent_resolution,
  review_log, candidate_exclusions, label_sessions
  (iran 012/014의 백엔드 쓰기 부분만 이관)

Phase 2-5: 빌드 + 기동 검증 완료
- ./mvnw clean compile 성공
- spring-boot:run으로 기동 → Flyway가 V001~V005 자동 적용
- /actuator/health UP 확인
- 14개 테이블 + flyway_schema_history 생성 확인
- ADMIN 245건, OPERATOR 22건, 다른 역할 13건 권한 시드 확인

Phase 2 임시 SecurityConfig: 모든 요청 permitAll
(Phase 3에서 JWT 필터 + 트리 기반 권한 체크로 전환 예정)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:01:13 +09:00
e6319a571c refactor: 모노레포 구조로 전환 (frontend/ + backend/ + database/)
Phase 1: 모노레포 디렉토리 구조 구축

- 기존 React 프로젝트를 frontend/ 디렉토리로 이동 (git mv)
- backend/ 디렉토리 생성 (Phase 2에서 Spring Boot 초기화)
- database/migration/ 디렉토리 생성 (Phase 2에서 Flyway 마이그레이션)
- 루트 .gitignore에 frontend/, backend/ 경로 반영
- 루트 CLAUDE.md를 모노레포 가이드로 갱신
- Makefile 추가 (dev/build/lint 통합 명령)
- frontend/vite.config.ts에 /api → :8080 백엔드 proxy 설정
- .githooks/pre-commit을 모노레포 구조에 맞게 갱신
  (frontend/ 변경 시 frontend/ 내부에서 검증)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 08:47:24 +09:00
1eccbd7a72 chore: 팀 워크플로우 초기화 + Prettier + 타입 에러 수정
- /init-project로 팀 표준 워크플로우 적용 (CLAUDE.md, settings.json hooks, pre-commit)
- Prettier + eslint-config-prettier 설치 및 ESLint 연동
- format/format:check npm 스크립트 추가
- vite-env.d.ts 추가 (import.meta.env 타입 정의)
- pre-commit 차단 해제: GearDetection/BaseChart 타입 캐스팅

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 08:44:28 +09:00
7a9ece5f0f Merge pull request 'ci: Gitea Actions 자동배포 워크플로우 추가' (#1) from feature/add-cicd into develop 2026-04-06 14:13:24 +09:00
6e1fd0918a ci: Gitea Actions 자동배포 워크플로우 추가
main push 시 npm build → kcg-ai-monitoring.gc-si.dev 자동 배포.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 14:12:55 +09:00
c0ce01eaf6 chore: 팀 워크플로우 기반 초기 프로젝트 구성
KCG AI 기반 불법조업 탐지·차단 플랫폼 프론트엔드.
React 19 + TypeScript 5.9 + Vite 8 + MapLibre + deck.gl + Zustand + Tailwind CSS.
SFR 20개 전체 UI 구현 완료, 백엔드 연동 대기.

- npm + Nexus 프록시 레지스트리 설정
- 팀 워크플로우 v1.6.1 부트스트랩 파일 배치
- .githooks (commit-msg, post-checkout)
- package.json name: kcg-ai-monitoring v0.1.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 14:11:29 +09:00