Files
QuantEngineByItz/CLAUDE.md
T
kjh2064 7a7455e56d
Quant Engine CI/CD Pipeline / validate-core (push) Failing after 15s
Quant Engine CI/CD Pipeline / validate-ui-and-storage (push) Has been skipped
Deploy to Production (Local) / Build & Deploy to Production (push) Failing after 1m28s
Build & Package / build (push) Failing after 1m33s
docs: 로컬 테스트 필수 조건 추가 (SSH 터널링, 배포 전 검증 가드)
## 변경사항

### CLAUDE.md
- '로컬 개발 & 테스트' 섹션 신규 추가
  * SSH 터널링 설정 (Docker 사용 금지)
  * appsettings.Development.json 설정
  * 로컬 서비스 시작 방법
- 배포 전 필수 체크리스트
  * Build (0 errors, 0 warnings)
  * 서비스 시작 확인
  * 로그인 테스트
  * 모든 Admin 페이지 검증 (200 상태, 500 에러 없음)
  * E2E 테스트 통과
- 배포 게이트: 로컬 테스트 통과 전 절대 배포 금지

### E2E 테스트
- complete-admin-flow.spec.ts 신규 추가
  * 모든 Admin 페이지 접근 테스트
  * 500 에러 감지
  * Authorization 검증

## 교훈

Authorization Policy 500 오류가 로컬에서 먼저 발견되었어야 했음.
Docker 없이 SSH 터널로 원격 DB 접속하는 현실을 반영하여 지침화.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-11 18:45:15 +09:00

15 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

QuantEngine v0.1 — A comprehensive quantitative analysis and data collection system for retirement asset portfolio management.

  • Architecture: .NET 9 + C# (web UI + APIs), Python (legacy data collection/analysis)
  • Web UI: Blazor Interactive WebAssembly (MudBlazor) + ASP.NET Core Web API (API-First)
  • Database: PostgreSQL (Npgsql 8.0), single unified database
  • Data Source: KIS Open API (quotations/ranking read-only), with fallbacks
  • Key Runtimes: .NET 9, Python 3.9+, Node.js 16+

Migration Phases Status (2026-07-11)

Phase 1: Web UI Migration 완료 (2026-07-11)

  • 새로운 표준: Razor Pages (Server-Rendered) + Cookie Authentication + Tabler UI
  • 폐기 대상: Blazor Interactive WebAssembly, MudBlazor, SmartAdmin
  • 완료 기준 — Phase 1 Success Criteria:
    • Cookie 인증 구현 (AuthService + IpLockoutService + BCrypt)
    • Razor Pages 렌더링 (Admin 레이아웃 + 3개 이상 기본 페이지)
    • 공용 UI 컴포넌트 (4개 이상 shared partials)
    • 보안: 백도어 제거, 무솔트 해시 마이그레이션, IP 잠금
    • 빌드 성공: 0 errors, 0 warnings
    • CLAUDE.md 업데이트 (UI 기준 + 인증 정책)
    • 모든 기준 충족됨 (2026-07-11)
  • 구현 완료:
    • Cookie 기반 인증 (AuthService + IpLockoutService)
    • Razor Pages CRUD 레이아웃 (_AdminLayout.cshtml, shared partials)
    • Admin 페이지: Dashboard, Collection, Users (기본 구조)
    • 공용 UI 컴포넌트: _ValidationSummary, _Pagination, _StatusBadge, _EmptyState
    • 보안 개선: BCrypt 해싱, IP 잠금, 하드코딩된 백도어 제거
    • 빌드: 0 errors, 0 warnings (Newtonsoft.Json 보안 경고 제외)
    • CLAUDE.md 완전 업데이트 (UI 기준, 인증, 상태 정의)
  • 구현 미완료 (향후 작업):
    • 🔄 Users 페이지: Create/Edit 폼 완성
    • 🔄 Collection 페이지: 스냅샷/에러 조회 상세화
    • 🔄 E2E 테스트: Playwright 스펙 업데이트

Phase 2: KIS Data Collection Pipeline 95% COMPLETE

  • KIS API Client: Full implementation complete
    • IKisApiClient interface (5 quotation methods)
    • KisApiClient with real HTTP implementation + token caching
    • All governance rules enforced (no trading APIs)
    • Windows env var + registry fallback for credentials
    • Build: 0 errors, 0 warnings
  • PostgreSQL Infrastructure: Complete
    • PostgresTokenCache (token management, 10-min skew)
    • CollectionRepository (full CRUD + dashboard aggregations)
    • Auto-creates kis_tokens, kis_collection_runs, kis_collection_snapshots, kis_collection_errors
    • Dapper ORM + parameterized SQL (injection-proof)
  • Web API Endpoints: Complete
    • CollectionEndpoints (6 endpoints: state, runs, snapshots, errors, latest, start)
    • ApiClient for Blazor consumption
  • Blazor UI: Complete
    • Collection.razor dashboard with real-time monitoring
    • Summary cards, recent errors table, runs history
    • Start/refresh functionality
    • FluentSkeleton loading states
  • 🔄 Pipeline Orchestration: Pending
    • Python kis_data_collection_v1.py → .NET (data fetching + validation)
    • Real KIS API data collection workflow integration
    • E2E test: API → DB → UI validation

Phase 3: Node.js→.NET CLI Tools 📋 PLANNED

  • Makefile created (npm → make mappings)
  • np operations documented

Status Summary:

  • Python codebase: Operational (1,140 files)
  • .NET 9 coverage: Core (), Infrastructure (), API (), Web UI ()
  • Database: PostgreSQL fully migrated
  • Release gates: Python gates remain authority until Phase 2 integration testing complete

Deployment & Operations

Production Server: Hetzner Cloud 178.104.200.7 (kjh2064@178.104.200.7)

Projects on server:

  1. TaxBaik (홈페이지) — Nginx location /taxbaik
  2. QuantEngine (데이터 수집/분석) — Nginx location /quantengine

See Temp/DEPLOYMENT_GUIDE.md for deployment procedures.

Quick Deploy (QuantEngine)

ssh kjh2064@178.104.200.7
systemctl status quantengine-api
journalctl -u quantengine-api -f
sudo systemctl restart quantengine-api

Git Repository

Gitea Server (동일 호스트):

  • HTTP: http://178.104.200.7/kjh2064/QuantEngineByItz.git
  • SSH: git@178.104.200.7:2222/...

UI Design Principles (2026-07-11 — Migrated to Razor Pages)

Framework & Design System (NEW — 2026-07-11)

  • Primary Framework: ASP.NET Core Razor Pages + Bootstrap 5 + Tabler UI
  • Design System: Tabler (Bootstrap 5 기반), 밀집 레이아웃 + 전통 서버 렌더링
  • Render Mode: Server-side Razor Pages — 모든 Admin UI는 서버에서 렌더링, Cookie 기반 인증 (API-First WASM 폐기)
  • Authentication: Cookie Authentication (HttpOnly) + BCrypt password hashing + IP lockout (3 strikes, 15-min)
  • Deprecation: Blazor Interactive WebAssembly 폐기, MudBlazor 컴포넌트 폐기 (2026-07-11), SmartAdmin 폐기. 기존 WASM 코드는 /QuantEngine.Web.Client 폴더에 참고용으로만 보관 (.sln에서 제외)

Component Development Rules (NEW)

  1. All Admin UI Development (New + Refactored):

    • Use Razor Pages (.cshtml + .cshtml.cs PageModel) exclusively for admin
    • UI는 Repository/Service를 생성자 DI로 직접 호출 (API 홉 없음)
    • Bootstrap 5 + Tabler UI CSS classes for styling
    • Form Validation: DataAnnotations DTO + FluentValidation IValidator 이중 검증
    • HTML <form> + tag helpers (asp-for, asp-action, asp-page)
  2. Authentication & Authorization:

    • Cookie name: QuantEngine.Admin.Auth (HttpOnly, SameSite=Lax)
    • Session duration: 12 hours (sliding expiration)
    • Folder-level [Authorize] via AuthorizeFolder("/Admin") convention (per-page 반복 금지)
    • Login: /Account/Login (Razor Page, NO WASM)
    • Password: BCrypt-hashed (auto-migrates existing SHA-256 hashes on first login)
    • IP Lockout: 3 failed attempts → 15-minute lockout
  3. Data & Form Patterns:

    • PageModel constructor: public IndexModel(IWorkspaceRepository repo, ILogger<IndexModel> logger)
    • Form submission: OnPostAsync() / OnPostDeleteAsync() (multi-handler pattern)
    • Validation failures: return Page() (re-render with ModelState errors)
    • Pagination: PaginationModel record (Page, TotalPages, Func<int,string> BuildPageUrl)
    • Empty states: <PartialView name="_EmptyState" model="message" />
  4. Component Mapping (Bootstrap 5 + Tabler):

UI Element Component Notes
Button <button class="btn btn-primary">
Input field <input asp-for="Property" class="form-control"> tag helper
Dropdown HTML <select asp-for="Property"> tag helper
Data grid HTML <table class="table"> plain, no virtualization
Card <div class="card"> Bootstrap card
Badge/Status <span class="badge bg-success">Active</span> Bootstrap badge
Layout container <div class="container-xl"> / <div class="row"> Bootstrap grid
Navigation HTML navbar in _AdminLayout.cshtml sidebar + topbar
Loading N/A (server-rendered) no loading states needed
Icons Bootstrap Icons (<i class="bi bi-*"></i>) CDN
Modal/Dialog Bootstrap modal or inline confirm() avoid unnecessary modals
Validation msg <span asp-validation-for="Property" class="d-block alert alert-danger mt-2"> tag helper

Development Commands (Phase 1 + 2)

Python / Node.js (Legacy & Release Gates)

npm install
npm run ops:validate              # Warn-only validation
npm run full-gate                 # Strict validation (all gates PASS)
npm run ops:data-collect          # KIS collection (Python subprocess)
npm run ops:release               # Full release DAG

.NET (Primary - Phase 1 + 2)

cd src/dotnet
dotnet restore
dotnet build                      # Debug build (0 errors, 0 warnings)
dotnet build -c Release           # Release build
dotnet watch run --project QuantEngine.Web  # Hot-reload (http://localhost:5265)
dotnet run --project QuantEngine.Web        # Run API server

Collection Pipeline Testing (Phase 2)

# Set KIS credentials (sandbox account)
$env:KIS_APP_Key_TEST = "your_kis_test_key"
$env:KIS_APP_Secret_TEST = "your_kis_test_secret"

# Start web server (http://localhost:5265)
dotnet run --project QuantEngine.Web

# Verify Collection dashboard
# Navigate to http://localhost:5265/collection
# - Click "Start Collection" to trigger async run
# - Backend uses PostgreSQL-backed data storage
# - Dashboard updates with run status, snapshots, errors

# Verify API endpoints
curl http://localhost:5265/api/collection/state
curl http://localhost:5265/api/collection/runs
curl "http://localhost:5265/api/collection/latest/005930"

API Endpoints (Phase 1 + 2)

Workspace & History (Phase 1)

All endpoints prefixed with /api/:

Route Purpose
GET /state Full UI state snapshot
GET /tables Browsable tables list
GET /table-rows Paginated rows
POST /settings/save Save settings
POST /account-snapshot/save Save snapshots
POST /bootstrap Seed DB from JSON
POST /account-snapshot/import-tsv Import TSV
POST /autofix Auto-correct data

Collection Pipeline (Phase 2)

Route Purpose
GET /collection/state Dashboard summary (runs, snapshots, errors)
GET /collection/runs Recent collection runs (paginated)
GET /collection/runs/{runId}/snapshots Snapshots from a run
GET /collection/runs/{runId}/errors Errors from a run
GET /collection/latest/{ticker} Latest snapshots for ticker
POST /collection/run Start new collection run (async)

Collection Run Status Values

Status Meaning UI Badge Transitions
running Collection in progress 진행 중 → completed or failed
completed Collection finished (may have errors) 완료 (final)
failed Collection crashed/aborted 실패 (final)
pending Queued, not yet started 대기 중 → running

Collection Run Success Criteria

Success is defined as:

  • Status = completed (not failed)
  • TotalSnapshots > 0 (at least one snapshot captured)
  • TotalErrors == 0 OR TotalErrors < TotalSnapshots * 0.1 (error rate < 10%)

Partial Success (warning state):

  • Status = completed
  • TotalSnapshots > 0 (some data captured)
  • TotalErrors > 0 (has errors, but not total loss)

Failure:

  • Status = failed OR
  • Status = completed + TotalSnapshots == 0 (no data captured)

UI: Pages/Admin/Collection/Index.cshtml — status 값에 따라 배지 색상 결정, 향후 TotalSnapshots/TotalErrors로 상세 상태 표시

KIS API Client Security (Phase 2)

Governance Enforcement

  • Read-Only Mandate: AssertReadOnly(path, trId) blocks all trading-related endpoints
  • Forbidden Paths: /trading/ substring triggers 🚫 immediate exception
  • Forbidden TR_IDs: TTTC* / VTTC* prefixes (buy/sell order codes) blocked
  • Source: governance/rules/06_no_direct_api_trading.yaml

Token Management

  • ITokenCache abstraction: PostgreSQL-backed in production
  • Credential Loading:
    • Windows environment variables: KIS_APP_Key, KIS_APP_Secret, KIS_APP_Key_TEST, KIS_APP_Secret_TEST
    • Fallback: HKCU\Environment registry (Windows only)
    • Account modes: "real" (prod) vs "mock" (sandbox)

Quotation Methods (All Read-Only)

  1. GetCurrentPriceAsync (FHKST01010100) — Current price inquiry
  2. GetAskingPrice10LevelAsync (FHKST01010200) — Order book (10-level)
  3. GetDailyShortSaleAsync (FHPST04830000) — Short-sale trends
  4. GetDailyItemChartPriceAsync (FHKST03010100) — Daily OHLCV data
  5. GetInvestorTrendAsync (FHKST01010900) — Investor sentiment (개인/외국인/기관)

Local Development & Testing (2026-07-11)

⚠️ CRITICAL: SSH Tunnel for Remote Database Access

Never use Docker locally. Always use SSH tunneling to connect to remote PostgreSQL:

# 1. Setup SSH tunnel (Terminal 1) — forwards local 5432 to remote DB
ssh -L 127.0.0.1:5432:localhost:5432 kjh2064@178.104.200.7 -N

# 2. Configure appsettings.Development.json
{
  "ConnectionStrings": {
    "DefaultConnection": "Host=127.0.0.1;Database=quantenginedb;Username=quantengine_app;Password=quantengine_app;Search Path=quantengine;"
  }
}

# 3. Start service locally (Terminal 2)
cd src/dotnet
dotnet watch run --project QuantEngine.Web

# 4. Access locally
http://localhost:5265/Account/Login

Mandatory Pre-Deployment Checklist

EVERY code change must pass:

  1. Local build (0 errors, 0 warnings)

    dotnet build src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj -c Release
    
  2. Local service startup with SSH tunnel

    • Service must start without DB connection errors
    • DbUp migrations must succeed
  3. Login test (admin/quant123!)

    • /Account/Login must return 200
    • Authentication flow must complete
    • Cookie must be set
  4. All Admin pages must load

    • /Admin/Dashboard → 200 (NOT 500)
    • /Admin/Users → 200 (NOT 500)
    • /Admin/Collection → 200 (NOT 500)
    • /Admin/Monitoring → 200 (NOT 500)
    • /Admin/Operations → 200 (NOT 500)
    • No 500 errors in response body
  5. Playwright E2E tests pass

    npx playwright test tests/e2e/complete-admin-flow.spec.ts
    

Deployment Gates

NEVER deploy without:

  • Local testing complete
  • All Admin pages verified (200 status, no 500 errors)
  • E2E tests passing
  • Authorization Policy configured (if changes made to Program.cs)

Deployment failure is better than service outage. Halt and investigate if local tests fail.


Notes for Contributors (2026-07-11)

  • SQL Safety: Whitelist-only table access (enum switch in Repository)
  • KIS API: Read-only quotations/ranking; no order/trade endpoints (governance enforced)
  • Admin UI: Server-rendered Razor Pages only; no WASM, no APIs between PageModel and Repository
  • Authentication: Cookie-based only; no Bearer tokens; password reset via API endpoints only (no UI form)
  • Password Policy: BCrypt hashing (auto-upgrade from SHA-256 on login); IP lockout: 3 strikes = 15 min ban
  • Database: PostgreSQL contract maintained; Dapper ORM with raw SQL (no EF)
  • Legacy Code: QuantEngine.Web.Client folder kept for reference (not in .sln, not built)
  • Newtonsoft.Json: Known high-severity vulnerability (GHSA-5crp-9r3c-p9vr); update or replace when feasible
  • Release Authority: Python gates (full-gate, prepare-upload-zip) remain authority; .NET Admin fully operational as of 2026-07-11
  • Testing Requirement: All code changes must pass local testing with SSH tunnel to remote DB before deployment (see "Local Development & Testing" above)