Compare commits
27 Commits
4ef7a54ad5
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f60fbf655 | |||
| f68fb10bac | |||
| c1b7d29eb8 | |||
| ce3505cd33 | |||
| e97397ddbf | |||
| 6ed3de2749 | |||
| 3e7120c041 | |||
| 784f4bdbfb | |||
| 28e1a8775f | |||
| fe8ff44d3f | |||
| d5d630a816 | |||
| 60022ed214 | |||
| 90bbb1860d | |||
| 3e4d545e01 | |||
| e4290ef3c6 | |||
| 4de9339163 | |||
| bdb9262f4e | |||
| 8bd678c7c7 | |||
| 24c1cce542 | |||
| 1255e67765 | |||
| a02543981e | |||
| fdfd50bdca | |||
| 227b563ba2 | |||
| 5c5d9bfee7 | |||
| 2220f9f807 | |||
| c06c24d8bc | |||
| 0b503c20af |
+177
-160
@@ -2,193 +2,210 @@ name: Deploy to Production
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: deploy-prod-main
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
DEPLOY_HOST: 172.17.0.1
|
||||
DEPLOY_HOST: 178.104.200.7
|
||||
DEPLOY_USER: kjh2064
|
||||
DEPLOY_PATH: /home/kjh2064/quantengine_active
|
||||
SERVICE_NAME: quantengine
|
||||
DOTNET_VERSION: '10.0.x'
|
||||
TELEGRAM_BOT_TOKEN_DEFAULT: "8734507814:AAFyacLMai8GB4K-hQ_Nd3t3D01A-h1ZdV0"
|
||||
QUANTENGINE_DB_NAME: quantenginedb
|
||||
QUANTENGINE_DB_USER: quantengine_app
|
||||
TELEGRAM_BOT_TOKEN_DEFAULT: "8734507814:AAFyacLMai8GB4K-hQ_Nd3t3D01A-H1ZdV0"
|
||||
TELEGRAM_CHAT_ID_DEFAULT: "-5460205872"
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
name: Build & Deploy to Production
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Install Python Dependencies
|
||||
run: pip install pyyaml openpyxl requests
|
||||
- name: Install Python Dependencies
|
||||
run: pip install pyyaml openpyxl requests
|
||||
|
||||
- name: "[GATE] Run Core Validations"
|
||||
run: |
|
||||
echo "🔐 Running critical CI validations..."
|
||||
python3 tools/validate_no_direct_api_trading_v1.py || exit 1
|
||||
python3 tools/validate_specs.py || exit 1
|
||||
echo "✅ All critical validations passed"
|
||||
- name: "[GATE] Run Core Validations"
|
||||
run: |
|
||||
echo "🔐 Running critical CI validations..."
|
||||
python3 tools/validate_no_direct_api_trading_v1.py || exit 1
|
||||
python3 tools/validate_specs.py || exit 1
|
||||
echo "✅ All critical validations passed"
|
||||
|
||||
- name: Ensure Temp Directory and Mock Packet
|
||||
run: |
|
||||
mkdir -p Temp
|
||||
# 빈 패킷 객체를 생성하여 dotnet test/run 시 IO Exception 방어
|
||||
if [ ! -f Temp/final_decision_packet_active.json ]; then
|
||||
echo '{"active_decision": "PASS", "details": "CI dummy packet"}' > Temp/final_decision_packet_active.json
|
||||
fi
|
||||
- name: Ensure Temp Directory and Mock Packet
|
||||
run: |
|
||||
mkdir -p Temp
|
||||
if [ ! -f Temp/final_decision_packet_active.json ]; then
|
||||
echo '{"active_decision": "PASS", "details": "CI dummy packet"}' > Temp/final_decision_packet_active.json
|
||||
fi
|
||||
|
||||
- name: Restore Dependencies
|
||||
run: dotnet restore src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj
|
||||
- name: Restore Dependencies
|
||||
run: dotnet restore src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj
|
||||
|
||||
- name: Build Release
|
||||
run: |
|
||||
dotnet build src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj \
|
||||
-c Release \
|
||||
--no-restore \
|
||||
-p:Version=1.0.${{ github.run_number }}
|
||||
- name: Build Release
|
||||
run: |
|
||||
dotnet build src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj \
|
||||
-c Release \
|
||||
--no-restore
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
if [ -d tests/unit ]; then
|
||||
dotnet test tests/unit \
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
dotnet test src/dotnet/QuantEngine.Core.Tests/QuantEngine.Core.Tests.csproj \
|
||||
-c Release \
|
||||
--no-build
|
||||
|
||||
- name: Publish Release Package
|
||||
run: |
|
||||
dotnet publish src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj \
|
||||
-c Release \
|
||||
--no-build \
|
||||
|| echo "⚠️ Some tests failed (non-blocking for web service)"
|
||||
fi
|
||||
-o ./publish
|
||||
|
||||
- name: Publish Release Package
|
||||
run: |
|
||||
dotnet publish src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj \
|
||||
-c Release \
|
||||
--no-build \
|
||||
-o ./publish-output
|
||||
- name: Generate Build Info
|
||||
run: |
|
||||
COMMIT_HASH=$(git rev-parse --short HEAD)
|
||||
BUILD_TIME=$(date -d "+9 hours" +'%Y-%m-%d %H:%M:%S KST')
|
||||
mkdir -p ./publish/wwwroot
|
||||
printf '{\n "version": "1.0.%s-%s",\n "built": "%s"\n}\n' "${{ github.run_number }}" "$COMMIT_HASH" "$BUILD_TIME" > ./publish/wwwroot/version.json
|
||||
echo "✓ Generated version info: 1.0.${{ github.run_number }}-$COMMIT_HASH @ $BUILD_TIME"
|
||||
|
||||
- name: Generate Build Info
|
||||
run: |
|
||||
COMMIT_HASH=$(git rev-parse --short HEAD)
|
||||
BUILD_TIME=$(date -d "+9 hours" +'%Y-%m-%d %H:%M:%S KST')
|
||||
mkdir -p ./publish-output/wwwroot
|
||||
printf '{\n "version": "1.0.%s-%s",\n "built": "%s"\n}\n' "${{ github.run_number }}" "$COMMIT_HASH" "$BUILD_TIME" > ./publish-output/wwwroot/version.json
|
||||
echo "✓ Generated version info: 1.0.${{ github.run_number }}-$COMMIT_HASH @ $BUILD_TIME"
|
||||
|
||||
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
# SSH_PRIVATE_KEY가 평문 PEM이든 base64든 유연하게 처리
|
||||
if echo "${{ secrets.SSH_PRIVATE_KEY }}" | grep -q "BEGIN"; then
|
||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
|
||||
else
|
||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" | base64 -d > ~/.ssh/id_ed25519 || echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
|
||||
fi
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
ssh-keyscan -H ${{ env.DEPLOY_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true
|
||||
|
||||
- name: Package Artifact
|
||||
run: |
|
||||
tar -czf quant_engine_deploy.tgz -C ./publish-output .
|
||||
echo "✓ Package size: $(du -sh quant_engine_deploy.tgz | cut -f1)"
|
||||
|
||||
- name: Deploy & Verify on Server
|
||||
run: |
|
||||
set -e
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
COMMIT=$(git rev-parse --short HEAD)
|
||||
DEPLOY_HOST="${{ env.DEPLOY_HOST }}"
|
||||
DEPLOY_USER="${{ env.DEPLOY_USER }}"
|
||||
|
||||
# 텔레그램 설정 바인딩 (Secret에 없을 경우 기본값 백업 사용)
|
||||
TELEGRAM_BOT_TOKEN="${{ secrets.TELEGRAM_BOT_TOKEN }}"
|
||||
[ -z "$TELEGRAM_BOT_TOKEN" ] && TELEGRAM_BOT_TOKEN="${{ env.TELEGRAM_BOT_TOKEN_DEFAULT }}"
|
||||
TELEGRAM_CHAT_ID="${{ secrets.TELEGRAM_CHAT_ID }}"
|
||||
[ -z "$TELEGRAM_CHAT_ID" ] && TELEGRAM_CHAT_ID="${{ env.TELEGRAM_CHAT_ID_DEFAULT }}"
|
||||
|
||||
send_telegram() {
|
||||
local text="$1"
|
||||
curl -fsS -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
||||
-d "chat_id=${TELEGRAM_CHAT_ID}" \
|
||||
--data-urlencode "text=${text}" \
|
||||
-d "parse_mode=HTML" >/dev/null || true
|
||||
}
|
||||
|
||||
notify_failure() {
|
||||
local exit_code=$?
|
||||
send_telegram "❌ <b>QuantEngine 배포 실패</b>
|
||||
|
||||
커밋: <code>${COMMIT}</code>
|
||||
시간: <code>${TIMESTAMP}</code>
|
||||
단계: deploy-to-prod (SSH Execution)"
|
||||
exit "$exit_code"
|
||||
}
|
||||
|
||||
trap notify_failure ERR
|
||||
|
||||
echo "=== Deploying QuantEngine $COMMIT ($TIMESTAMP) ==="
|
||||
|
||||
# 1. 아티팩트 복사
|
||||
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 \
|
||||
quant_engine_deploy.tgz "$DEPLOY_USER@$DEPLOY_HOST:/tmp/quantengine_${TIMESTAMP}.tgz"
|
||||
|
||||
# 2. 원격 배포 명령어 통합 (SSH 1회 연결)
|
||||
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 \
|
||||
-o ServerAliveInterval=10 \
|
||||
"$DEPLOY_USER@$DEPLOY_HOST" bash << REMOTE
|
||||
set -e
|
||||
DEPLOY_HOME="/home/kjh2064"
|
||||
DEPLOY_DIR="\$DEPLOY_HOME/deployments/quantengine_${TIMESTAMP}"
|
||||
|
||||
echo "--- [1/4] 압축 해제 ---"
|
||||
mkdir -p "\$DEPLOY_DIR"
|
||||
tar -xzf "/tmp/quantengine_${TIMESTAMP}.tgz" -C "\$DEPLOY_DIR"
|
||||
rm -f "/tmp/quantengine_${TIMESTAMP}.tgz"
|
||||
|
||||
echo "--- [2/4] 심볼릭 링크 전환 ---"
|
||||
ln -sfn "\$DEPLOY_DIR" "${{ env.DEPLOY_PATH }}"
|
||||
|
||||
echo "--- [3/4] 서비스 재시작 ---"
|
||||
sudo /usr/bin/systemctl restart ${{ env.SERVICE_NAME }}
|
||||
|
||||
echo "--- [4/4] 헬스 체크 ---"
|
||||
ATTEMPTS=20
|
||||
for i in \$(seq 1 \$ATTEMPTS); do
|
||||
STATUS=\$(curl -sf -o /dev/null -w '%{http_code}' http://127.0.0.1:5000/ 2>/dev/null || echo "000")
|
||||
if [ "\$STATUS" = "200" ]; then
|
||||
echo "✓ 헬스체크 성공 (시도 \$i/\$ATTEMPTS, HTTP 200)"
|
||||
# 구 배포 폴더 정리 (최근 5개만 보존)
|
||||
ls -1dt \$DEPLOY_HOME/deployments/quantengine_* 2>/dev/null | tail -n +6 | xargs rm -rf 2>/dev/null || true
|
||||
exit 0
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
if echo "${{ secrets.SSH_PRIVATE_KEY }}" | grep -q "BEGIN"; then
|
||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
|
||||
else
|
||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" | base64 -d > ~/.ssh/id_ed25519 || echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
|
||||
fi
|
||||
if [ "\$i" -eq "\$ATTEMPTS" ]; then
|
||||
echo "=== FATAL: 서비스가 헬스체크 응답을 하지 않음 ===" >&2
|
||||
systemctl is-active ${{ env.SERVICE_NAME }} >&2 || true
|
||||
journalctl -u ${{ env.SERVICE_NAME }} --no-pager -n 50 >&2
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
ssh-keyscan -H ${{ env.DEPLOY_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true
|
||||
|
||||
- name: Prepare QuantEngine DB Env
|
||||
run: |
|
||||
mkdir -p ./deploy
|
||||
cat > ./deploy/quantengine.env <<EOF
|
||||
ConnectionStrings__DefaultConnection=Host=127.0.0.1;Database=${QUANTENGINE_DB_NAME};Username=${QUANTENGINE_DB_USER};Password=${{ secrets.QUANTENGINE_DB_PASSWORD }};Search Path=quantengine;
|
||||
EOF
|
||||
chmod 600 ./deploy/quantengine.env
|
||||
|
||||
- name: Package Artifact
|
||||
run: |
|
||||
tar -czf quantengine.tar.gz -C ./publish .
|
||||
echo "✓ Package size: $(du -sh quantengine.tar.gz | cut -f1)"
|
||||
|
||||
- name: Deploy & Verify on Server
|
||||
run: |
|
||||
set -e
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
COMMIT=$(git rev-parse --short HEAD)
|
||||
DEPLOY_HOST="${{ env.DEPLOY_HOST }}"
|
||||
DEPLOY_USER="${{ env.DEPLOY_USER }}"
|
||||
|
||||
TELEGRAM_BOT_TOKEN="${{ secrets.TELEGRAM_BOT_TOKEN }}"
|
||||
[ -z "$TELEGRAM_BOT_TOKEN" ] && TELEGRAM_BOT_TOKEN="${{ env.TELEGRAM_BOT_TOKEN_DEFAULT }}"
|
||||
TELEGRAM_CHAT_ID="${{ secrets.TELEGRAM_CHAT_ID }}"
|
||||
[ -z "$TELEGRAM_CHAT_ID" ] && TELEGRAM_CHAT_ID="${{ env.TELEGRAM_CHAT_ID_DEFAULT }}"
|
||||
|
||||
send_telegram() {
|
||||
local text="$1"
|
||||
curl -fsS -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
||||
-d "chat_id=${TELEGRAM_CHAT_ID}" \
|
||||
--data-urlencode "text=${text}" \
|
||||
-d "parse_mode=HTML" >/dev/null || true
|
||||
}
|
||||
|
||||
notify_failure() {
|
||||
local exit_code=$?
|
||||
send_telegram "❌ <b>QuantEngine 배포 실패</b>
|
||||
|
||||
커밋: <code>${COMMIT}</code>
|
||||
시간: <code>${TIMESTAMP}</code>
|
||||
단계: deploy-to-prod (SSH Execution)"
|
||||
exit "$exit_code"
|
||||
}
|
||||
|
||||
trap notify_failure ERR
|
||||
|
||||
echo "=== Deploying QuantEngine $COMMIT ($TIMESTAMP) ==="
|
||||
|
||||
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 \
|
||||
"$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p /home/kjh2064/tmp"
|
||||
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 \
|
||||
quantengine.tar.gz "$DEPLOY_USER@$DEPLOY_HOST:/home/kjh2064/tmp/quantengine.tar.gz"
|
||||
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 \
|
||||
tools/deploy_quantengine.sh "$DEPLOY_USER@$DEPLOY_HOST:/home/kjh2064/tmp/deploy.sh"
|
||||
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 \
|
||||
deploy/quantengine.env "$DEPLOY_USER@$DEPLOY_HOST:/home/kjh2064/tmp/quantengine.env"
|
||||
|
||||
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 \
|
||||
"$DEPLOY_USER@$DEPLOY_HOST" "chmod +x /home/kjh2064/tmp/deploy.sh && CI_DEPLOY=1 /home/kjh2064/tmp/deploy.sh"
|
||||
|
||||
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 \
|
||||
"$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p /home/kjh2064/.config && install -m 600 /home/kjh2064/tmp/quantengine.env /home/kjh2064/.config/quantengine.env && rm -f /home/kjh2064/tmp/quantengine.env"
|
||||
|
||||
echo "=== Verifying Loopback Health ==="
|
||||
loopback_headers=$(ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 "$DEPLOY_USER@$DEPLOY_HOST" "curl -s -D - -o /dev/null http://127.0.0.1:5000/")
|
||||
echo "$loopback_headers"
|
||||
if ! printf '%s' "$loopback_headers" | grep -qE '^HTTP/1\.[01] 30[12] '; then
|
||||
echo "Loopback health check failed for quantengine" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! printf '%s' "$loopback_headers" | grep -qiE '^Location: /login'; then
|
||||
echo "Loopback redirect target is unexpected" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo " 대기 중... (\$i/\$ATTEMPTS, HTTP \$STATUS)"
|
||||
sleep 3
|
||||
done
|
||||
REMOTE
|
||||
|
||||
echo "✓ 배포 완료: quantengine_${TIMESTAMP} @ $DEPLOY_HOST"
|
||||
send_telegram "✅ <b>QuantEngine 배포 완료</b>
|
||||
|
||||
커밋: <code>${COMMIT}</code>
|
||||
시간: <code>${TIMESTAMP}</code>
|
||||
대상: <code>${DEPLOY_HOST}</code>"
|
||||
echo "=== Verifying Favicon Assets ==="
|
||||
favicon_svg_code=$(curl -s -o /dev/null -w "%{http_code}" "http://${DEPLOY_HOST}/favicon.svg")
|
||||
favicon_png_code=$(curl -s -o /dev/null -w "%{http_code}" "http://${DEPLOY_HOST}/favicon.png")
|
||||
echo "/favicon.svg -> ${favicon_svg_code}"
|
||||
echo "/favicon.png -> ${favicon_png_code}"
|
||||
if [ "$favicon_svg_code" != "200" ] && [ "$favicon_png_code" != "200" ]; then
|
||||
echo "Favicon assets are not reachable after deploy" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Verifying Public Routes ==="
|
||||
public_root_headers=$(curl -s -D - -o /dev/null "https://quant.taxbaik.com/")
|
||||
login_headers=$(curl -s -D - -o /dev/null "https://quant.taxbaik.com/login")
|
||||
|
||||
public_root_code=$(printf '%s' "$public_root_headers" | awk 'NR==1 {print $2}')
|
||||
login_code=$(printf '%s' "$login_headers" | awk 'NR==1 {print $2}')
|
||||
|
||||
echo "https://quant.taxbaik.com/ -> ${public_root_code}"
|
||||
echo "https://quant.taxbaik.com/login -> ${login_code}"
|
||||
|
||||
if [ "$public_root_code" != "302" ] && [ "$public_root_code" != "200" ]; then
|
||||
echo "Deployment content check failed for public root" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$login_code" != "200" ]; then
|
||||
echo "Deployment content check failed for login page" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ 배포 완료: quantengine_${TIMESTAMP} @ $DEPLOY_HOST"
|
||||
send_telegram "✅ <b>QuantEngine 배포 완료</b>
|
||||
|
||||
커밋: <code>${COMMIT}</code>
|
||||
시간: <code>${TIMESTAMP}</code>
|
||||
대상: <code>${DEPLOY_HOST}</code>"
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
name: Snapshot Admin Deployment
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: snapshot-admin-deploy-main
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
DEPLOY_HOST: 178.104.200.7
|
||||
DEPLOY_USER: kjh2064
|
||||
TELEGRAM_BOT_TOKEN_DEFAULT: "8734507814:AAFyacLMai8GB4K-hQ_Nd3t3D01A-h1ZdV0"
|
||||
TELEGRAM_CHAT_ID_DEFAULT: "-5460205872"
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup .NET SDK
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '10.0.x'
|
||||
|
||||
- name: Publish Blazor Web App
|
||||
run: |
|
||||
echo "[deploy] publishing .NET 10 Blazor app"
|
||||
dotnet publish src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj -c Release -o ./publish
|
||||
|
||||
- name: Generate Build Info
|
||||
run: |
|
||||
COMMIT_HASH=$(git rev-parse --short HEAD)
|
||||
BUILD_TIME=$(date -d "+9 hours" +'%Y-%m-%d %H:%M:%S KST')
|
||||
mkdir -p ./publish/wwwroot
|
||||
printf '{\n "version": "1.0.%s-%s",\n "built": "%s"\n}\n' "${{ github.run_number }}" "$COMMIT_HASH" "$BUILD_TIME" > ./publish/wwwroot/version.json
|
||||
echo "✓ Generated version info: 1.0.${{ github.run_number }}-$COMMIT_HASH @ $BUILD_TIME"
|
||||
|
||||
|
||||
- name: Compress Artifact
|
||||
run: |
|
||||
echo "[deploy] compressing publish output"
|
||||
tar -czf quantengine.tar.gz -C ./publish .
|
||||
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
if echo "${{ secrets.SSH_PRIVATE_KEY }}" | grep -q "BEGIN"; then
|
||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
|
||||
else
|
||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" | base64 -d > ~/.ssh/id_ed25519 || echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
|
||||
fi
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
ssh-keyscan -H ${{ env.DEPLOY_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true
|
||||
|
||||
- name: Deploy & Verify on Server
|
||||
run: |
|
||||
set -e
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
COMMIT=$(git rev-parse --short HEAD)
|
||||
DEPLOY_HOST="${{ env.DEPLOY_HOST }}"
|
||||
DEPLOY_USER="${{ env.DEPLOY_USER }}"
|
||||
|
||||
TELEGRAM_BOT_TOKEN="${{ secrets.TELEGRAM_BOT_TOKEN }}"
|
||||
[ -z "$TELEGRAM_BOT_TOKEN" ] && TELEGRAM_BOT_TOKEN="${{ env.TELEGRAM_BOT_TOKEN_DEFAULT }}"
|
||||
TELEGRAM_CHAT_ID="${{ secrets.TELEGRAM_CHAT_ID }}"
|
||||
[ -z "$TELEGRAM_CHAT_ID" ] && TELEGRAM_CHAT_ID="${{ env.TELEGRAM_CHAT_ID_DEFAULT }}"
|
||||
|
||||
send_telegram() {
|
||||
local text="$1"
|
||||
curl -fsS -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
||||
-d "chat_id=${TELEGRAM_CHAT_ID}" \
|
||||
--data-urlencode "text=${text}" \
|
||||
-d "parse_mode=HTML" >/dev/null || true
|
||||
}
|
||||
|
||||
notify_failure() {
|
||||
local exit_code=$?
|
||||
send_telegram "❌ <b>Snapshot Admin 배포 실패</b>
|
||||
|
||||
커밋: <code>${COMMIT}</code>
|
||||
시간: <code>${TIMESTAMP}</code>
|
||||
단계: snapshot_admin_deploy (Deploy Execution)"
|
||||
exit "$exit_code"
|
||||
}
|
||||
|
||||
trap notify_failure ERR
|
||||
|
||||
echo "=== Deploying Snapshot Admin $COMMIT ($TIMESTAMP) ==="
|
||||
|
||||
# 1. 원격지 임시 폴더 생성 및 업로드
|
||||
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 "$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p /home/kjh2064/tmp"
|
||||
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 quantengine.tar.gz "$DEPLOY_USER@$DEPLOY_HOST:/home/kjh2064/tmp/quantengine.tar.gz"
|
||||
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 tools/deploy_quantengine.sh "$DEPLOY_USER@$DEPLOY_HOST:/home/kjh2064/tmp/deploy.sh"
|
||||
|
||||
# 2. 배포 스크립트 실행
|
||||
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 "$DEPLOY_USER@$DEPLOY_HOST" "chmod +x /home/kjh2064/tmp/deploy.sh && /home/kjh2064/tmp/deploy.sh"
|
||||
|
||||
# 3. 배포 성공 검증
|
||||
echo "=== Verifying Public Routes ==="
|
||||
root_html=$(curl -sf "http://${DEPLOY_HOST}/quant/" 2>/dev/null || echo "")
|
||||
ops_html=$(curl -sf "http://${DEPLOY_HOST}/quant/operations" 2>/dev/null || echo "")
|
||||
|
||||
root_code=$(printf '%s' "$root_html" | grep -q "Quant Engine" && echo 200 || echo 500)
|
||||
ops_code=$(printf '%s' "$ops_html" | grep -q "Operational Report" && echo 200 || echo 500)
|
||||
|
||||
echo "/quant/ -> ${root_code}"
|
||||
echo "/quant/operations -> ${ops_code}"
|
||||
|
||||
if [ "$root_code" != "200" ]; then
|
||||
echo "Deployment content check failed for /quant/" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$ops_code" != "200" ]; then
|
||||
echo "Deployment content check failed for /quant/operations" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ 배포 완료: quantengine_${TIMESTAMP} @ $DEPLOY_HOST"
|
||||
send_telegram "✅ <b>Snapshot Admin 배포 완료</b>
|
||||
|
||||
커밋: <code>${COMMIT}</code>
|
||||
시간: <code>${TIMESTAMP}</code>
|
||||
대상: <code>${DEPLOY_HOST}</code>"
|
||||
@@ -10,6 +10,13 @@ Temp/
|
||||
dist/
|
||||
outputs/
|
||||
|
||||
# .NET 빌드 산출물
|
||||
**/bin/
|
||||
**/obj/
|
||||
publish-output/
|
||||
*.user
|
||||
*.suo
|
||||
|
||||
# 런타임 감사 로그 (append-only, 매 DAG 실행마다 증가)
|
||||
runtime/lineage_events.jsonl
|
||||
|
||||
|
||||
@@ -110,6 +110,8 @@
|
||||
- D+2 영업일 기준 현금을 즉시방어 자산으로 간주하고, 목표 예산 5억 원을 기준으로 포지션 사이징 및 리스크 버킷을 제어한다.
|
||||
- 매주 주말 리밸런싱(rebalance_required=true) 및 매월 1일/11일/21일 중간점검(mid_check_required=true) 운영 cadence를 준수한다.
|
||||
- 커밋, 푸쉬, PR 작업 시 반드시 로컬의 .gs 파일을 Google Apps Script 원격 프로젝트에 업로드(python tools/deploy_gas.py 실행)하고, 사용자에게 스프레드시트 상의 스크립트 실행(예: runDataFeed)을 통한 검증을 유도 및 가이드해야 한다.
|
||||
- QuantEngine 배포는 CI 전용이다. 로컬에서 서버로 산출물을 직접 업로드하거나 `scp`/`rsync`로 수동 반영하지 않는다. 실배포는 `.gitea/workflows/deploy-prod.yml`만 사용하며, 로컬 스크립트는 CI 환경에서만 실행 가능해야 한다.
|
||||
- 원격 서버 확인이 필요하면 `ssh kjh2064@178.104.200.7` 접속을 먼저 시도하고, 사용자에게 매번 접속 확인을 요구하지 말고 직접 상태/로그/헬스체크를 수집한 뒤 결과만 보고한다.
|
||||
|
||||
## 4. 보고 규칙
|
||||
- 모든 숫자에는 반드시 provenance(출처)를 남기며, 출처가 유효하지 않거나 없는 숫자는 보고서 표기를 전면 배제(DATA_MISSING 처리)한다.
|
||||
@@ -135,7 +137,8 @@
|
||||
- **임시 파일 관리**: 개발/디버깅 목적의 모든 휘발성 임시 파일 및 로그는 반드시 `Temp/` 디렉토리 하위에서만 생성해야 하며, 루트나 다른 패키지 경로에 임시 파일을 만드는 것은 금지한다. 불가피하게 생성할 경우 반드시 접두사/접미사 규칙(`debug_*`, `tmp_*`, `mock_*`, `*_temp.*`)을 준수하여 `.gitignore`에 필터링되도록 한다.
|
||||
|
||||
## 5b. Blazor & API-First 개발 규칙 (TaxBaik 참조 모델 적용)
|
||||
- **API-First 아키텍처**: Blazor Server UI 계층은 비즈니스 로직이나 DB에 직접 결합되지 않고, `IXxxBrowserClient` 등의 추상화된 API 클라이언트(HTTP/RESTful)를 통해서만 백엔드 API와 통신한다.
|
||||
- **렌더 모드 표준**: Blazor **Interactive WebAssembly** 를 기본 렌더 모드로 한다. InteractiveServer 는 사용하지 않으며, UI 컴포넌트는 **MudBlazor** 로 통일한다 (Fluent UI 는 폐기).
|
||||
- **API-First 아키텍처**: Blazor Interactive WebAssembly UI 계층은 비즈니스 로직이나 DB에 직접 결합되지 않고, `IXxxBrowserClient` 등의 추상화된 API 클라이언트(HTTP/RESTful)를 통해서만 백엔드 API와 통신한다.
|
||||
- **이중 토큰 인증 패턴**: Access Token(15분) 및 Refresh Token(7일) 이중 토큰 패턴을 적용하며, HttpClient 요청 시 401 Unauthorized를 가로채어 자동으로 localStorage의 Refresh Token으로 토큰을 자동 갱신 및 재시도하는 `TokenRefreshHandler` (DelegatingHandler) 구조를 준수한다.
|
||||
- **실시간 알림 (SignalR)**: 실시간 알림 기능은 상태를 직접 동기화하는 용도가 아닌 단순 Event-driven 브로드캐스트 알림으로 설계하며, 클라이언트는 알림 수신 후 API 호출을 통해 최종 데이터를 검증 및 동기화한다.
|
||||
- **UI/UX 구현**:
|
||||
|
||||
@@ -7,29 +7,31 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
**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 WebAssembly (Fluent UI Blazor v5) + ASP.NET Core Web API
|
||||
- **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-06-29)
|
||||
|
||||
**Phase 1: Web UI Migration** ✅ COMPLETE
|
||||
- Blazor WebAssembly with Fluent UI v5 (RC: 5.0.0-rc.4-26177.1)
|
||||
- MudBlazor completely deprecated (0% remaining)
|
||||
**Phase 1: Web UI Migration** 🔄 정책 전환 (2026-06-30)
|
||||
- **신규 표준**: Blazor **Interactive WebAssembly** 렌더 모드 + **MudBlazor** 컴포넌트 + API-First
|
||||
- **이전 표준(폐기)**: Fluent UI Blazor v5 / InteractiveServer 렌더 모드는 더 이상 사용하지 않음
|
||||
- Pages: Home, Workspace, Collection, Tables, MainLayout
|
||||
- Build: 0 errors, 6 Razor RC warnings (acceptable)
|
||||
- 코드 전환 작업은 `docs/WBS_10_DOTNET_MIGRATION_HARDENING_2026_06_30.md` 의 **WBS-A7** 로 추적
|
||||
|
||||
**Phase 2: KIS Data Collection Pipeline** 🔄 IN PROGRESS
|
||||
**Phase 2: KIS Data Collection Pipeline** ✅ 95% COMPLETE
|
||||
- ✅ KIS API Client: Full implementation complete
|
||||
- IKisApiClient interface (5 quotation methods)
|
||||
- KisApiClient (with security enforcement, token caching)
|
||||
- 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
|
||||
- ITokenCache → PostgresTokenCache (token management)
|
||||
- ICollectionRepository → CollectionRepository (data storage)
|
||||
- IDataCollectionStore (abstraction layer)
|
||||
- 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
|
||||
@@ -37,7 +39,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
- Collection.razor dashboard with real-time monitoring
|
||||
- Summary cards, recent errors table, runs history
|
||||
- Start/refresh functionality
|
||||
- 🔄 Integration Testing: Pending (Python subprocess fallback active)
|
||||
- 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)
|
||||
@@ -78,22 +84,24 @@ sudo systemctl restart quantengine-api
|
||||
|
||||
### Framework & Design System
|
||||
|
||||
- **Primary Framework**: [Fluent UI Blazor v5](https://v5.fluentui-blazor.net/)
|
||||
- **Design System**: Microsoft Fluent Design System (WCAG 2.1 AA)
|
||||
- **Deprecation**: MudBlazor is deprecated. Migrate all existing pages to Fluent UI v5 progressively.
|
||||
- **Primary Framework**: [MudBlazor](https://mudblazor.com/)
|
||||
- **Design System**: Material Design (MudBlazor), 고밀도/대량 데이터 성능 우선
|
||||
- **Render Mode**: **Interactive WebAssembly** 를 기본 렌더 모드로 한다 (API-First). InteractiveServer 는 사용하지 않는다.
|
||||
- **Deprecation**: **Fluent UI Blazor v5 는 폐기**한다. 기존 Fluent UI 페이지는 MudBlazor 로 점진 이전한다.
|
||||
|
||||
### Component Development Rules
|
||||
|
||||
1. **All UI Development** (New + Refactored):
|
||||
- Use Fluent UI Blazor v5 components exclusively
|
||||
- Fall back to pure HTML/CSS if Fluent v5 doesn't provide
|
||||
- **Never introduce MudBlazor components** (deprecated)
|
||||
- Progressively migrate existing MudBlazor to Fluent v5
|
||||
- Use **MudBlazor** components exclusively
|
||||
- Fall back to pure HTML/CSS if MudBlazor doesn't provide
|
||||
- **Never introduce Fluent UI components** (deprecated)
|
||||
- Progressively migrate existing Fluent UI to MudBlazor
|
||||
- **API-First**: UI 는 DB/비즈니스 로직에 직접 결합하지 않고 추상화된 API 클라이언트(HTTP)로만 통신 (AGENTS.md §5b 준수)
|
||||
|
||||
2. **Loading States** (Priority order):
|
||||
- `<FluentSkeleton>` — **Default** for lists, cards, dashboards, detail pages
|
||||
- `<MudSkeleton>` — **Default** for lists, cards, dashboards, detail pages
|
||||
- Pure HTML `<div class="skeleton">` — For custom layouts
|
||||
- `MudProgressCircular` / `MudProgressLinear` — Exception only (existing legacy)
|
||||
- `<MudProgressCircular>` / `<MudProgressLinear>` — 명시적 진행 표시가 필요한 경우
|
||||
- Blocking spinners — **Avoid**
|
||||
|
||||
3. **Data Rendering Pattern**:
|
||||
@@ -101,21 +109,22 @@ sudo systemctl restart quantengine-api
|
||||
- On data arrival: Replace skeleton with actual UI
|
||||
- Never show blank states while loading
|
||||
|
||||
4. **Component Mapping** (Fluent UI v5):
|
||||
4. **Component Mapping** (MudBlazor):
|
||||
|
||||
| UI Element | Fluent UI Component | Alternative |
|
||||
| UI Element | MudBlazor Component | Alternative |
|
||||
|-----------|-------------------|-------------|
|
||||
| Button | `<FluentButton>` | - |
|
||||
| Input field | `<FluentTextField>` | HTML `<input>` |
|
||||
| Dropdown | `<FluentSelect>` | HTML `<select>` |
|
||||
| Data grid | `<FluentDataGrid>` | HTML `<table>` |
|
||||
| Card | `<FluentCard>` | HTML `<div class="card">` |
|
||||
| Badge/Status | `<FluentBadge>` | HTML `<span>` |
|
||||
| Layout container | `<FluentStack>` | HTML `<div>` |
|
||||
| Accordion | `<FluentAccordion>` | HTML `<details>` |
|
||||
| Navigation | `<FluentNavMenu>` | HTML `<nav>` |
|
||||
| Loading | `<FluentSkeleton>` | CSS skeleton animation |
|
||||
| Icons | `<FluentIcon>` | SVG inline |
|
||||
| Button | `<MudButton>` | - |
|
||||
| Input field | `<MudTextField>` | HTML `<input>` |
|
||||
| Dropdown | `<MudSelect>` | HTML `<select>` |
|
||||
| Data grid | `<MudDataGrid Dense Virtualize>` | HTML `<table>` |
|
||||
| Card | `<MudCard>` | HTML `<div class="card">` |
|
||||
| Badge/Status | `<MudBadge>` / `<MudChip>` | HTML `<span>` |
|
||||
| Layout container | `<MudStack>` / `<MudGrid>` | HTML `<div>` |
|
||||
| Accordion | `<MudExpansionPanels>` | HTML `<details>` |
|
||||
| Navigation | `<MudNavMenu>` | HTML `<nav>` |
|
||||
| Loading | `<MudSkeleton>` | CSS skeleton animation |
|
||||
| Icons | `<MudIcon>` | SVG inline |
|
||||
| Modal/Dialog | `<MudDialog>` (CRUD: 모달 패턴, 삭제: ConfirmDialog) | - |
|
||||
|
||||
## Development Commands (Phase 1 + 2)
|
||||
|
||||
@@ -130,29 +139,33 @@ npm run ops:release # Full release DAG
|
||||
|
||||
### .NET (Primary - Phase 1 + 2)
|
||||
```powershell
|
||||
cd dotnet
|
||||
cd src/dotnet
|
||||
dotnet restore
|
||||
dotnet build # Debug build
|
||||
dotnet build -c Release # Release build (recommended)
|
||||
dotnet watch run --project src/QuantEngine.Web # Hot-reload (http://localhost:5000)
|
||||
dotnet run --project src/QuantEngine.Web # Run API server
|
||||
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)
|
||||
```powershell
|
||||
# Set credentials (Windows environment variables)
|
||||
$env:KIS_APP_Key_TEST = "mock_key"
|
||||
$env:KIS_APP_Secret_TEST = "mock_secret"
|
||||
# Set KIS credentials (sandbox account)
|
||||
$env:KIS_APP_Key_TEST = "your_kis_test_key"
|
||||
$env:KIS_APP_Secret_TEST = "your_kis_test_secret"
|
||||
|
||||
# Verify Blazor Collection page
|
||||
# Navigate to http://localhost:5000/collection
|
||||
# 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
|
||||
# - API initiates Python subprocess (temporary Phase 2 design)
|
||||
# - Backend uses PostgreSQL-backed data storage
|
||||
# - Dashboard updates with run status, snapshots, errors
|
||||
|
||||
# Verify API directly
|
||||
curl http://localhost:5000/api/collection/state
|
||||
curl http://localhost:5000/api/collection/runs
|
||||
# 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)
|
||||
|
||||
@@ -144,7 +144,7 @@ npm run prepare-upload-zip
|
||||
## CI / 배포 분리
|
||||
|
||||
- `.gitea/workflows/ci.yml`은 검증 전용이다.
|
||||
- `.gitea/workflows/snapshot_admin_deploy.yml`은 실배포 전용이다.
|
||||
- `.gitea/workflows/deploy-prod.yml`은 실배포 전용이다.
|
||||
- 공개 URL `http://178.104.200.7/quant/` 갱신은 deploy workflow 성공 여부로 판단한다.
|
||||
|
||||
## 운영 리포트 계약
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
# HTTP 80 ➜ HTTPS 443 Redirect
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name taxbaik.com www.taxbaik.com gitea.taxbaik.com quant.taxbaik.com;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
# TaxBaik 홈페이지 (통합 앱)
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name taxbaik.com www.taxbaik.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/taxbaik.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/taxbaik.com/privkey.pem;
|
||||
|
||||
client_max_body_size 512M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:5001/taxbaik/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
|
||||
# Gitea (코드 저장소)
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name gitea.taxbaik.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/taxbaik.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/taxbaik.com/privkey.pem;
|
||||
|
||||
client_max_body_size 512M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300;
|
||||
proxy_connect_timeout 300;
|
||||
proxy_send_timeout 300;
|
||||
}
|
||||
}
|
||||
|
||||
# QuantEngine (Blazor Admin)
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name quant.taxbaik.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/taxbaik.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/taxbaik.com/privkey.pem;
|
||||
|
||||
client_max_body_size 512M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:5000/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
+62
-68
@@ -16,8 +16,8 @@
|
||||
| 3.2 | [Python 가상 환경](#32-python-가상-환경) | `~/.venv`, `python3` 사용 규칙 |
|
||||
| 3.3 | [주요 Python 패키지](#33-주요-python-패키지-시스템) | 시스템/venv 패키지 구분 |
|
||||
| 4 | [서비스 아키텍처](#4-서비스-아키텍처) | 포트 맵, Nginx 리버스 프록시 |
|
||||
| 4.1 | [포트 맵](#41-포트-맵) | 22, 80, 2222, 3000, 5000, 5432 |
|
||||
| 4.2 | [Nginx 리버스 프록시](#42-nginx-리버스-프록시) | `/` → Gitea, `/quant/` → Blazor |
|
||||
| 4.1 | [포트 맵](#41-포트-맵) | 22, 80, 443, 2222, 3000, 5000, 5001, 5432 |
|
||||
| 4.2 | [Nginx 리버스 프록시](#42-nginx-리버스-프록시) | 도메인 가상 호스트 기반 분기 |
|
||||
| 5 | [Gitea](#5-gitea) | Docker Compose 설정, 시크릿, 데이터 경로 |
|
||||
| 5.1 | [Docker Compose](#51-docker-compose) | `gitea:1.26.4`, PG 연동 |
|
||||
| 5.2 | [시크릿 관리](#52-시크릿-관리) | `/opt/stacks/gitea/.env` |
|
||||
@@ -117,55 +117,30 @@ boto3, cryptography, Jinja2, jsonschema, fail2ban 등 시스템 레벨로 설치
|
||||
| 포트 | 서비스 | 바인드 | 비고 |
|
||||
|---|---|---|---|
|
||||
| **22** | SSH | `0.0.0.0` | 공개키 전용 |
|
||||
| **80** | Nginx (리버스 프록시) | `0.0.0.0` | 외부 진입점 |
|
||||
| **80** | Nginx (HTTP) | `0.0.0.0` | 443 HTTPS로 리다이렉트 |
|
||||
| **443** | Nginx (HTTPS) | `0.0.0.0` | SSL 가상 호스트 진입점 |
|
||||
| **2222** | Gitea SSH | `0.0.0.0` | Git SSH 접속 |
|
||||
| **3000** | Gitea Web | `127.0.0.1` | Nginx 프록시 경유 |
|
||||
| **5000** | QuantEngine Blazor | `127.0.0.1` | Nginx `/quant/` 경유 |
|
||||
| **3000** | Gitea Web | `127.0.0.1` | Nginx 프록시 경유 (`gitea.taxbaik.com`) |
|
||||
| **5000** | QuantEngine Blazor | `127.0.0.1` | Nginx 프록시 경유 (`quant.taxbaik.com`) |
|
||||
| **5001** | TaxBaik 홈페이지 | `127.0.0.1` | Nginx 프록시 경유 (`taxbaik.com` / `www.taxbaik.com`) |
|
||||
| **5432** | PostgreSQL | `127.0.0.1` + `172.17.0.1` | 로컬 + Docker 네트워크 |
|
||||
|
||||
### 4.2. Nginx 리버스 프록시
|
||||
|
||||
```nginx
|
||||
# /etc/nginx/sites-enabled/gitea-ip.conf
|
||||
도메인 기반 가상 호스트(Virtual Host) 방식을 사용하여 각 도메인 요청을 내부 서비스로 연결하고, SSL(HTTPS)을 필수로 적용합니다. HTTP(80) 포트 요청은 자동으로 HTTPS(443)로 리다이렉트됩니다.
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
server_name _;
|
||||
client_max_body_size 512M;
|
||||
상세 Nginx 설정 백업은 `deploy/nginx-taxbaik-domains.conf`에 위치합니다.
|
||||
|
||||
# QuantEngine Blazor Web App
|
||||
location /quant/ {
|
||||
proxy_pass http://127.0.0.1:5000/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Gitea (기본)
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300;
|
||||
proxy_connect_timeout 300;
|
||||
proxy_send_timeout 300;
|
||||
}
|
||||
}
|
||||
```
|
||||
#### 가상 호스트 설정 개요
|
||||
- **TaxBaik 홈페이지** (`https://taxbaik.com`, `https://www.taxbaik.com`) ➜ `http://127.0.0.1:5001/taxbaik/`
|
||||
- **Gitea (코드 저장소)** (`https://gitea.taxbaik.com`) ➜ `http://127.0.0.1:3000`
|
||||
- **QuantEngine (Blazor Admin)** (`https://quant.taxbaik.com`) ➜ `http://127.0.0.1:5000/`
|
||||
|
||||
**라우팅 요약**:
|
||||
- `http://178.104.200.7/` → Gitea Web UI
|
||||
- `http://178.104.200.7/quant/` → QuantEngine Blazor Admin
|
||||
- `ssh://178.104.200.7:2222` → Gitea Git SSH
|
||||
- `https://taxbaik.com` & `https://www.taxbaik.com` ➜ TaxBaik 홈페이지 (통합 앱)
|
||||
- `https://gitea.taxbaik.com` ➜ Gitea Web UI
|
||||
- `https://quant.taxbaik.com` ➜ QuantEngine Blazor Admin
|
||||
- `ssh://git@gitea.taxbaik.com:2222` ➜ Gitea Git SSH
|
||||
|
||||
## 5. Gitea
|
||||
|
||||
@@ -231,8 +206,9 @@ services:
|
||||
### 6.4. CI / 배포 분리
|
||||
|
||||
- `.gitea/workflows/ci.yml`: 검증 전용. 스펙/공식/리포트/아티팩트 생성까지만 수행한다.
|
||||
- `.gitea/workflows/snapshot_admin_deploy.yml`: 실배포 전용. `dotnet publish` 후 `tools/deploy_quantengine.sh`를 이용해 `/home/kjh2064/quantengine_active`로 반영한다.
|
||||
- 공개 URL `/quant/` 갱신은 `snapshot_admin_deploy.yml`의 성공 여부를 기준으로 판단한다.
|
||||
- `.gitea/workflows/deploy-prod.yml`: 실배포 전용. `dotnet publish` 후 `tools/deploy_quantengine.sh`를 이용해 `/home/kjh2064/quantengine_active`로 반영한다.
|
||||
- 수동 배포 금지: 로컬에서 `scp`/`rsync`로 `quantengine_active`를 갱신하지 않는다. 배포는 CI가 원격에서만 수행하고, 로컬 스크립트는 `CI_DEPLOY=1` 없이 실행되면 실패해야 한다.
|
||||
- 공개 URL 갱신은 `deploy-prod.yml`의 성공 여부를 기준으로 판단한다.
|
||||
|
||||
### 6.2. 러너 설정
|
||||
|
||||
@@ -335,8 +311,8 @@ ClientAliveCountMax 2
|
||||
|
||||
- **상태**: `ENABLED=yes` (`/etc/ufw/ufw.conf`)
|
||||
- **로그 레벨**: `low`
|
||||
- **외부 개방 포트**: 22 (SSH), 80 (HTTP/Nginx), 2222 (Gitea SSH)
|
||||
- **내부 전용**: 3000 (Gitea Web), 5000 (QuantEngine), 5432 (PostgreSQL)
|
||||
- **외부 개방 포트**: 22 (SSH), 80 (HTTP), 443 (HTTPS), 2222 (Gitea SSH)
|
||||
- **내부 전용**: 3000 (Gitea Web), 5000 (QuantEngine), 5001 (TaxBaik Web), 5432 (PostgreSQL)
|
||||
|
||||
> 상세 규칙 확인: `sudo ufw status numbered` (TTY + sudo 비밀번호 필요)
|
||||
|
||||
@@ -349,8 +325,9 @@ ClientAliveCountMax 2
|
||||
|
||||
- Gitea Web: `127.0.0.1:3000` (로컬 전용)
|
||||
- QuantEngine: `127.0.0.1:5000` (로컬 전용)
|
||||
- TaxBaik Web: `127.0.0.1:5001` (로컬 전용)
|
||||
- PostgreSQL: `127.0.0.1` + Docker bridge (`172.17.0.1`)
|
||||
- 외부 노출: SSH(22), HTTP(80), Gitea SSH(2222)만 개방
|
||||
- 외부 노출: SSH(22), HTTP(80), HTTPS(443), Gitea SSH(2222)만 개방
|
||||
|
||||
## 10. 디렉토리 맵
|
||||
|
||||
@@ -390,7 +367,7 @@ ClientAliveCountMax 2
|
||||
| **CI Runner** | Synology Act Runner | 6× `act_runner:latest` (Docker) |
|
||||
| **DB** | SQLite (파일 기반) | PostgreSQL 18 + SQLite (하이브리드) |
|
||||
| **웹 Admin** | 없음 | QuantEngine Blazor (.NET 10, MudBlazor) |
|
||||
| **리버스 프록시** | Synology 내장 | Nginx (`/` → Gitea, `/quant/` → Blazor) |
|
||||
| **리버스 프록시** | Synology 내장 | Nginx 도메인 가상 호스트 및 SSL (HTTPS) 적용 (`deploy/nginx-taxbaik-domains.conf`) |
|
||||
| **보안** | DSM 방화벽 | fail2ban + SSH 공개키 + 서비스 로컬바인드 |
|
||||
| **시크릿 관리** | `.secrets/kis_real.env` | `/opt/stacks/gitea/.env` |
|
||||
| **OS** | Synology DSM 7.x | Ubuntu 26.04 LTS |
|
||||
@@ -425,19 +402,9 @@ docker ps -a
|
||||
### QuantEngine 배포
|
||||
|
||||
```bash
|
||||
# 1. 새 배포 디렉토리 생성
|
||||
DEPLOY_DIR=~/deployments/quantengine_$(date +%Y%m%d_%H%M%S)
|
||||
mkdir -p "$DEPLOY_DIR"
|
||||
|
||||
# 2. 빌드 산출물 복사 (로컬에서 scp 또는 CI에서)
|
||||
scp -r publish/* kjh2064@178.104.200.7:"$DEPLOY_DIR"/
|
||||
|
||||
# 3. symlink 교체
|
||||
ln -sfn "$DEPLOY_DIR" ~/quantengine_active
|
||||
|
||||
# 4. 서비스 재시작
|
||||
sudo systemctl restart quantengine
|
||||
sudo systemctl status quantengine
|
||||
# CI에서만 배포
|
||||
# 로컬에서 scp/rsync로 quantengine_active를 갱신하지 않는다.
|
||||
# 배포는 .gitea/workflows/deploy-prod.yml 실행 결과로만 반영한다.
|
||||
```
|
||||
|
||||
### Gitea Act Runner 등록
|
||||
@@ -452,14 +419,20 @@ docker run -d \
|
||||
gitea/act_runner:latest
|
||||
```
|
||||
|
||||
### SSH 접속
|
||||
### SSH 접속 및 Git 원격 설정
|
||||
|
||||
```bash
|
||||
# Windows 로컬에서
|
||||
# Windows 로컬에서 서버 SSH 접속
|
||||
ssh kjh2064@178.104.200.7
|
||||
|
||||
# Gitea Git 접속
|
||||
git remote set-url origin ssh://git@178.104.200.7:2222/kjh2064/QuantEngineByItz.git
|
||||
# 로컬 프로젝트의 Git Remote URL 변경 (Gitea 도메인 기반 HTTPS 적용)
|
||||
# 1) 현재 설정된 remote url 확인
|
||||
git remote -v
|
||||
# 2) 새로운 도메인 주소로 원격 URL 변경
|
||||
git remote set-url origin https://gitea.taxbaik.com/kjh2064/QuantEngineByItz.git
|
||||
|
||||
# Gitea Git SSH 접속 (기존 2222 포트 유지)
|
||||
git remote set-url origin ssh://git@gitea.taxbaik.com:2222/kjh2064/QuantEngineByItz.git
|
||||
```
|
||||
|
||||
## 13. 검증 하네스
|
||||
@@ -514,6 +487,27 @@ ssh -T -p 2222 git@178.104.200.7 2>&1 | head -1
|
||||
|
||||
---
|
||||
|
||||
> **수집 일시**: 2026-06-26 09:55 KST
|
||||
> **수집 방법**: `ssh kjh2064@178.104.200.7` 라이브 명령 실행
|
||||
> **provenance**: 모든 값은 서버 실시간 명령 출력에서 추출. 임의 값 없음.
|
||||
## 14. 트러블슈팅 (Troubleshooting)
|
||||
|
||||
### 14.1. Certbot / APT 패키지 설치 시 Microsoft 리포지토리 404 오류
|
||||
- **증상**: `sudo apt-get update` 실행 시 Microsoft 패키지 저장소에서 `404 Not Found` 에러가 발생하며 패키지 목록 갱신이 중단되고, 이로 인해 `certbot` 설치가 `sudo: certbot: command not found` 에러로 실패하는 현상.
|
||||
- **원인**: Ubuntu 26.04 (Resolute) 환경에서 Microsoft의 잘못된 리포지토리(26.04 경로에 focal/20.04 릴리스가 설정된 상태)를 참조하여 발생.
|
||||
- **해결 방안**:
|
||||
1. 문제가 되는 Microsoft apt 소스 설정 파일을 삭제하거나 비활성화합니다.
|
||||
```bash
|
||||
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
|
||||
```
|
||||
2. APT 패키지 목록을 다시 업데이트하고 Certbot 및 Nginx 플러그인을 설치합니다.
|
||||
```bash
|
||||
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
|
||||
```
|
||||
3. 인증서 발급 및 설정을 적용합니다.
|
||||
```bash
|
||||
sudo certbot --nginx -d taxbaik.com -d www.taxbaik.com -d gitea.taxbaik.com -d quant.taxbaik.com --register-unsafely-without-email --agree-tos --non-interactive
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **수집 일시**: 2026-06-26 09:55 KST (추가 업데이트: 2026-07-01)
|
||||
> **수집 방법**: `ssh kjh2064@178.104.200.7` 라이브 명령 및 트러블슈팅 사례 수집
|
||||
> **provenance**: 모든 값은 서버 실시간 명령 출력 및 실제 오류 대처 조치 로그에서 추출. 임의 값 없음.
|
||||
|
||||
@@ -9,7 +9,7 @@ This document outlines the security configuration, role definitions, and access
|
||||
The Quant Investment Engine operates strictly within the `quantengine` schema to prevent namespace pollution and protect system catalog tables.
|
||||
|
||||
* **Schema**: `quantengine`
|
||||
* **Default Database**: `giteadb`
|
||||
* **Default Database**: `quantenginedb`
|
||||
|
||||
---
|
||||
|
||||
@@ -22,7 +22,7 @@ To ensure the principle of least privilege, we define three main database roles:
|
||||
* **Permissions**:
|
||||
```sql
|
||||
CREATE ROLE quantengine_owner WITH LOGIN PASSWORD 'OwnerPasswordSecure';
|
||||
GRANT ALL PRIVILEGES ON DATABASE giteadb TO quantengine_owner;
|
||||
GRANT ALL PRIVILEGES ON DATABASE quantenginedb TO quantengine_owner;
|
||||
GRANT ALL PRIVILEGES ON SCHEMA quantengine TO quantengine_owner;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA quantengine GRANT ALL ON TABLES TO quantengine_owner;
|
||||
```
|
||||
@@ -32,7 +32,7 @@ To ensure the principle of least privilege, we define three main database roles:
|
||||
* **Permissions**:
|
||||
```sql
|
||||
CREATE ROLE quantengine_app WITH LOGIN PASSWORD 'AppPasswordSecure';
|
||||
GRANT CONNECT ON DATABASE giteadb TO quantengine_app;
|
||||
GRANT CONNECT ON DATABASE quantenginedb TO quantengine_app;
|
||||
GRANT USAGE ON SCHEMA quantengine TO quantengine_app;
|
||||
|
||||
-- Grant CRUD permissions on tables & sequences
|
||||
@@ -48,7 +48,7 @@ To ensure the principle of least privilege, we define three main database roles:
|
||||
* **Permissions**:
|
||||
```sql
|
||||
CREATE ROLE quantengine_readonly WITH LOGIN PASSWORD 'ReadonlyPasswordSecure';
|
||||
GRANT CONNECT ON DATABASE giteadb TO quantengine_readonly;
|
||||
GRANT CONNECT ON DATABASE quantenginedb TO quantengine_readonly;
|
||||
GRANT USAGE ON SCHEMA quantengine TO quantengine_readonly;
|
||||
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA quantengine TO quantengine_readonly;
|
||||
@@ -63,7 +63,7 @@ To ensure the principle of least privilege, we define three main database roles:
|
||||
* Never store connection strings with plaintext passwords in version control.
|
||||
* `appsettings.json` must only contain placeholder configurations.
|
||||
* Inject the connection string at runtime using environment variables:
|
||||
`ConnectionStrings__DefaultConnection="Host=127.0.0.1;Database=giteadb;Username=quantengine_app;Password=YourSecurePassword;Search Path=quantengine;"`
|
||||
`ConnectionStrings__DefaultConnection="Host=127.0.0.1;Database=quantenginedb;Username=quantengine_app;Password=YourSecurePassword;Search Path=quantengine;"`
|
||||
|
||||
2. **Network Security**:
|
||||
* Bind PostgreSQL only to local interfaces (`127.0.0.1`) or secure private network interfaces.
|
||||
|
||||
+4
-2
@@ -925,7 +925,7 @@ python tools/validate_specs.py → PASS
|
||||
|------|------|
|
||||
| **작업** | `src/quant_engine/snapshot_admin_server_v1.py`(Python 어드민 웹 UI)를 Gitea CI/CD 배포 스텝을 통해 Synology NAS에서 상시 서비스로 운영할 수 있는지 검토 |
|
||||
| **현재 상태** | **기술적으로는 가능**. 기본 루프백 보호 + Basic Auth 게이트를 추가했고, Synology 외부 노출은 리버스 프록시 기반 POC로 가이드함. 실배포 검증은 아직 필요 |
|
||||
| **운영 분리** | `snapshot_admin.yml`은 `push`용 smoke 검증과 `workflow_dispatch`용 full 검증으로 분리하고, 배포는 별도 `snapshot_admin_deploy.yml` `workflow_dispatch`로 떼어냈다. `push`에서는 `Validate Snapshot Admin Workflow`까지만, full 검증에서는 `Validate Snapshot Admin Web UI`까지 수행한다. |
|
||||
| **운영 분리** | `snapshot_admin.yml`은 `push`용 smoke 검증과 `workflow_dispatch`용 full 검증으로 분리하고, 배포는 별도 `deploy-prod.yml` `workflow_dispatch`로 떼어냈다. `push`에서는 `Validate Snapshot Admin Workflow`까지만, full 검증에서는 `Validate Snapshot Admin Web UI`까지 수행한다. |
|
||||
| **runner 주의** | Gitea runner를 Docker mode로 두면 job 종료 시 `Cleaning up container` 로그가 남는다. host label로 재등록하면 job container 정리 로그를 피할 수 있다. |
|
||||
| **KIS 분리** | `kis_data_collection.yml`은 `workflow_dispatch`용 mock/config smoke와 `schedule`용 live collection으로 분리했다. 수동 디스패치는 실제 수집을 돌리지 않고, 실수집은 스케줄 전용이다. |
|
||||
| **담당 파일** | `.gitea/workflows/ci.yml`, `tools/run_snapshot_admin_server_v1.py`, `src/quant_engine/snapshot_admin_server_v1.py`, `docs/SYNOLOGY_SNAPSHOT_ADMIN_POC.md`, `docs/WBS_7_9_EVIDENCE_PACKET_FINAL.md` |
|
||||
@@ -1378,6 +1378,8 @@ WBS-8.8 (KIS 리팩터) — 독립적 (원격 병행)
|
||||
|
||||
### WBS-10: C#/.NET 엔진 고도화 (Phase 10, 2026-06~12)
|
||||
|
||||
> **📌 보강 문서(2026-06-30):** 본 WBS-10 의 다수 항목이 `완료` 표기되어 있으나 실측 결과 일부 괴리(10.6 파이프라인·10.9 보안 실질 미완성)가 확인되었다. 마이그레이션 완성 우선 + 상용화 잔여 작업의 재정의는 [WBS_10_DOTNET_MIGRATION_HARDENING_2026_06_30.md](./WBS_10_DOTNET_MIGRATION_HARDENING_2026_06_30.md) 참조.
|
||||
|
||||
> 현황 진단(2026-06-26): .NET 프로젝트는 Python 엔진(41 모듈, 14,500 LOC) 대비 5~10%(~1,400 LOC) 수준.
|
||||
> Domain 계산기 6개·데이터 모델 8개·KIS/Naver/Yahoo 클라이언트·PostgreSQL 마이그레이션·Blazor 대시보드 기본 구현 완료.
|
||||
> **미구현**: Application 서비스 일부, 공식 엔진, 하네스 주입, 파이프라인 오케스트레이터.
|
||||
@@ -1649,7 +1651,7 @@ WBS-10.1 (기반 결함 수정)
|
||||
| 10.10.2 | Dashboard 상태 페이지 — 데이터 비의존형 요약으로 단순화 | DB 실패 시에도 200 응답 (완료) |
|
||||
| 10.10.3 | Counter.razor / Weather.razor 기본 페이지 삭제, NavMenu 정비 | 불필요 페이지 0건, NavMenu에 Dashboard/Operations만 표시 (완료) |
|
||||
| 10.10.4 | 다크 모드 + 반응형 레이아웃 적용 | 브라우저 렌더링 정상 확인 (완료) |
|
||||
| 10.10.5 | 배포 동기화 | `snapshot_admin_deploy.yml`가 `/quant/`와 `/quant/operations` 공개 라우트를 배포 후 검증하도록 구성됨 (완료) |
|
||||
| 10.10.5 | 배포 동기화 | `deploy-prod.yml`가 공개 라우트를 배포 후 검증하도록 구성됨 (완료) |
|
||||
|
||||
**성공 하네스 (데이터 기준)**:
|
||||
```
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
# WBS-10 보강: .NET Core 마이그레이션 완성 & 상용화 로드맵 (2026-06-30)
|
||||
|
||||
> 본 문서는 [docs/ROADMAP_WBS.md](./ROADMAP_WBS.md) 의 **WBS-10(.NET 엔진 고도화)** 을 현 시점 실측 기준으로 재진단하고, 마이그레이션 완성과 단일 사용자 상용 운영에 필요한 잔여 작업을 재정의한다.
|
||||
>
|
||||
> **작성 배경:** 기존 WBS-10 의 다수 항목이 `완료` 로 표기되어 있으나, 2026-06-30 소스 실측 결과 **표기와 실제 상태 간 괴리**가 확인되었다. 본 문서는 그 괴리를 정리하고 실제 잔여 작업을 추적한다.
|
||||
>
|
||||
> **의사결정(사용자 확정):** ① 우선순위 = **마이그레이션 완성 우선**, ② 산출물 = **로드맵/WBS 문서**, ③ 인증 모델 = **단일 사용자 + 기본 보호**.
|
||||
|
||||
---
|
||||
|
||||
## 1. Context — 왜 이 보강이 필요한가
|
||||
|
||||
QuantEngine 은 은퇴자산 포트폴리오 운용을 위한 결정론적 퀀트 엔진이다. canonical 권위는 여전히 **Python 구현(219 파일, 24,683 lines)** 에 있고, `.NET 10` 마이그레이션은 Core / Application / Infrastructure / Web / Tools / Tests 6개 프로젝트로 구조화되어 Phase 1(Web UI)·Phase 2(KIS 수집)까지 도달했다.
|
||||
|
||||
그러나 다음 세 가지 근본 결손으로 마이그레이션 완료 및 상용 기준에 미달한다.
|
||||
|
||||
1. **마이그레이션 미완성** — 도메인 단일 권위가 Python 에 잔존. `PipelineOrchestrator` 가 실제 로직이 아닌 시뮬레이션 스텁. Python↔.NET 패리티가 일부 도메인 계산기에만 존재. GAS 공식 14건 미이관.
|
||||
2. **상용 운영 결손** — 소스에 하드코딩 시크릿 잔존, `.gitignore` 의 `bin/obj` 누락으로 빌드 산출물 git 추적, 헬스체크·메트릭·재시도·스케줄러·운영 구성(`appsettings.Production.json`) 부재.
|
||||
3. **검증 공백** — KIS→스냅샷→정성매도 전 구간 E2E 와 CI 커버리지 게이트 부재.
|
||||
|
||||
---
|
||||
|
||||
## 2. 표기 vs 실제 괴리 정리 (2026-06-30 실측)
|
||||
|
||||
| 기존 WBS | 기존 표기 | 실측 상태 | 괴리 / 조치 |
|
||||
|---|---|---|---|
|
||||
| WBS-10.6 파이프라인 오케스트레이터 | **완료** | `PipelineOrchestrator.cs` 가 각 단계를 `Task.Delay(10)` 로만 시뮬레이션. 실제 서비스 호출 없음 | 🔴 **실질 미완성.** → 본 문서 **A1** 로 재추적 |
|
||||
| WBS-10.9 보안 강화 | **완료** | `appsettings.json` 은 `Password=;` 처리됨. 그러나 `Program.cs:19` 텔레그램 토큰 평문, `Program.cs:34` DB 패스워드 폴백 평문 잔존. `.gitignore` 에 `bin/obj` 없음 → 산출물 git 추적 | 🔴 **부분 완료(핵심 누락).** → 본 문서 **P0** 로 재추적 |
|
||||
| WBS-10.8 데이터 수집 오케스트레이터 | **TODO** | 실제로는 `DataCollectionService.cs`(KIS 수집 오케스트레이션) 구현·커밋됨. 단 파일명/구조가 WBS 기재(`DataCollectionOrchestrator.cs`)와 불일치 | 🟡 **표기 미갱신.** → 본 문서 **A3** 로 정합화 |
|
||||
| WBS-10.3~10.5 도메인/공식/하네스 패리티 | 완료 | `DomainParityTests`, `FormulaEngineTests`, `HarnessInjector` 패리티 존재 확인 | ✅ 유효. 단 패리티 범위가 도메인 계산기에 한정 → 수집/정성매도/스냅샷은 미커버 (**A2** 확장) |
|
||||
| WBS-10.7 Application 서비스 | 부분 완료 | 4개 서비스 구현 확인 | ✅ 유효 |
|
||||
|
||||
> **핵심 시사점:** 기존 WBS-10 은 "완료" 표기가 실제보다 앞서 있다. 특히 보안(10.9)과 파이프라인(10.6)은 표기와 달리 **실질 미완성**이므로, 후속 작업은 표기를 신뢰하지 말고 본 문서의 실측 기준을 따른다.
|
||||
|
||||
---
|
||||
|
||||
## 3. 로드맵 (마이그레이션 완성 우선)
|
||||
|
||||
```
|
||||
[P0 선행 게이트] 보안·위생 차단 ──► 반드시 먼저
|
||||
│
|
||||
▼
|
||||
[Track A] 마이그레이션 완성 (PRIMARY) [Track B] 상용 안정화 (SECONDARY, 병행)
|
||||
A1 PipelineOrchestrator 실구현 B1 구성/시크릿 체계화
|
||||
A2 패리티 하네스 확장(수집·정성매도) B2 기본 인증(단일 사용자)
|
||||
A3 데이터 수집 파이프라인 E2E 정합화 B3 헬스체크·메트릭
|
||||
A4 정성매도/스냅샷 어드민 포팅 B4 재시도(Polly)·스케줄러
|
||||
A5 GAS 잔여 14개 공식 이관 B5 배포(Docker/CI 게이트)
|
||||
A6 SQLite→PostgreSQL 단일화 + Python 폐기 B6 통합/E2E 테스트·커버리지 게이트
|
||||
```
|
||||
|
||||
### 마일스톤
|
||||
|
||||
| 마일스톤 | 구성 | 완료 기준 |
|
||||
|---|---|---|
|
||||
| **M1 위생 확보** | P0 | git 에서 시크릿/산출물 제거, 시크릿 외부화·회전 |
|
||||
| **M2 패리티 기반** | A1·A2 | `.NET` 도메인이 Python 골든 벡터와 1:1 일치, 실 파이프라인 산출 |
|
||||
| **M3 수집 자립** | A3·A4·B4 | `.NET` 단독 KIS→스냅샷→정성매도 무인 실행 |
|
||||
| **M4 단일 권위 전환** | A5·A6 | Python 런타임 의존 제거, `.NET` canonical 승격 |
|
||||
| **M5 상용 운영** | B1~B6 | 단일 사용자 보호·관측·배포 체계 가동 |
|
||||
|
||||
---
|
||||
|
||||
## 4. WBS (작업 분해 구조)
|
||||
|
||||
각 항목: **목표 / 완료 판정(Acceptance) / 주요 파일 / 검증 명령**.
|
||||
|
||||
### P0 — 선행 보안·위생 게이트 (🔴 Critical, 최우선)
|
||||
|
||||
#### WBS-P0.1 빌드 산출물 git 추적 제거
|
||||
- **목표:** `.gitignore` 에 .NET 표준 패턴(`bin/`, `obj/`, `publish-output/`, `*.user`) 추가, 추적 중 산출물 `git rm -r --cached` 처리.
|
||||
- **판정:** `git status` 에 `bin/obj` 변경 미표시.
|
||||
- **파일:** `.gitignore`.
|
||||
- **검증:** `git status --porcelain | grep -E 'bin/|obj/'` → 0건.
|
||||
|
||||
#### WBS-P0.2 하드코딩 시크릿 제거·회전
|
||||
- **목표:** `Program.cs:19` 텔레그램 토큰·채팅ID, `Program.cs:34` DB 패스워드 폴백을 환경변수/`dotnet user-secrets`/`appsettings.Production.json`(비추적)로 이전. 노출 토큰·DB 비밀번호 **회전**.
|
||||
- **판정:** 소스 전역 시크릿 평문 0건, 구성 누락 시 앱 기동 거부(fail-fast).
|
||||
- **파일:** `Program.cs`, `appsettings*.json`, `Infrastructure/TelegramSink.cs`.
|
||||
- **검증:** `Select-String -Pattern '8734507814|C8RFlZ9f' src/dotnet -Recurse` → 0건.
|
||||
|
||||
#### WBS-P0.3 git 이력 시크릿 정리 (선택)
|
||||
- **목표:** 노출 토큰 회전 완료 시 이력 재작성 생략 가능. 회전 불가 시 `git filter-repo` 로 이력 제거 검토.
|
||||
- **판정:** 회전 완료 또는 이력 정리 완료 중 택1 기록.
|
||||
|
||||
> **주의:** WBS-10.9 가 `완료` 로 표기되어 있으나 위 P0.1·P0.2 는 미해결 상태다. 본 게이트 완료 전까지 후속 트랙 착수를 보류한다.
|
||||
|
||||
### Track A — 마이그레이션 완성 (PRIMARY)
|
||||
|
||||
#### WBS-A1 PipelineOrchestrator 실제 구현
|
||||
- **목표:** `Task.Delay` 시뮬레이션 제거. 7단계(수집→정규화→팩터→결정→리스크게이트→리포트→영속화)를 실제 서비스 호출로 연결.
|
||||
- **판정:** 입력 스냅샷에 대해 결정 패킷 산출, 각 단계 결과가 `engine_history` 에 기록.
|
||||
- **파일:** `QuantEngine.Application/Services/PipelineOrchestrator.cs`, 관련 `Services/*`.
|
||||
- **검증:** `dotnet test --filter Pipeline` → 실데이터 기반 산출물 `gate: PASS`.
|
||||
|
||||
#### WBS-A2 패리티 하네스 확장 (수집·정성매도)
|
||||
- **목표:** 기존 도메인 계산기 패리티(10.3~10.5)를 **수집 정규화·정성매도·하네스 주입 전체**로 확장. `spec/13_formula_registry.yaml`(149 공식) 기준 골든 벡터를 Python 에서 추출해 `.NET` 결과와 비교.
|
||||
- **판정:** 핵심 공식 전부 Python 과 동일 출력(부동소수 허용오차 내), 패리티 리포트 JSON 생성.
|
||||
- **파일:** `QuantEngine.Core.Tests/ParityTests/`, `tests/golden/`.
|
||||
- **검증:** `dotnet test --filter Parity` → 전건 PASS.
|
||||
|
||||
#### WBS-A3 데이터 수집 파이프라인 E2E 정합화
|
||||
- **목표:** `DataCollectionService.cs`(구현됨)를 기준으로 WBS 표기 정합화, `kis_data_collection_v1.py` 잔여 로직 완전 이관, KIS→PostgreSQL 스냅샷 E2E 검증. Naver/Yahoo 폴백 다중화 명문화.
|
||||
- **판정:** `.NET` 단독 실데이터 수집·저장 성공, 폴백 동작 확인.
|
||||
- **파일:** `Application/Services/DataCollectionService.cs`, `Infrastructure/External/*`.
|
||||
|
||||
#### WBS-A4 정성매도·스냅샷 어드민 포팅
|
||||
- **목표:** `qualitative_sell_strategy_v1.py`, `snapshot_admin_*_v1.py` 를 `.NET` 서비스/엔드포인트로 이관.
|
||||
- **판정:** 정성매도 5팩터 confluence 결과 Python 일치, 스냅샷 승인 워크플로우가 Web UI 에서 동작.
|
||||
- **파일:** `QuantEngine.Core/Domain/`, `QuantEngine.Web/Endpoints/`, `Components/Pages/`.
|
||||
|
||||
#### WBS-A5 GAS 잔여 14개 공식 이관
|
||||
- **목표:** `governance/gas_logic_migration_ledger_v1.yaml` 의 TODO 14건을 `.NET` 포팅 + parity.
|
||||
- **판정:** 원장 전 항목 `status: DONE`, parity 통과.
|
||||
- **파일:** `QuantEngine.Core/Domain/`, `governance/gas_logic_migration_ledger_v1.yaml`.
|
||||
|
||||
#### WBS-A6 SQLite→PostgreSQL 단일화 및 Python 런타임 폐기
|
||||
- **목표:** canonical DB 를 PostgreSQL 로 일원화, `src/quant_engine/*.db` 의존 제거, Python 런타임 도구를 `.NET`/`Tools` 로 대체.
|
||||
- **판정:** 운영 경로 Python 호출 0건, 모든 데이터 PostgreSQL 단일 소스.
|
||||
- **파일:** `Infrastructure/Data/DbMigrator.cs`, `Makefile`, `tools/`.
|
||||
|
||||
#### WBS-A7 UI 프레임워크 전환 — Fluent UI → MudBlazor + Interactive WebAssembly (2026-06-30 방침)
|
||||
- **배경:** UI 표준을 **MudBlazor** 컴포넌트 + **Interactive WebAssembly** 렌더 모드 + **API-First** 로 전환(방침 확정). 기존 Fluent UI v5 / InteractiveServer 는 폐기. 정책은 [CLAUDE.md](../CLAUDE.md) 및 [AGENTS.md](../AGENTS.md) §5b 에 반영 완료.
|
||||
- **목표:**
|
||||
- csproj 패키지 교체: `Microsoft.FluentUI.AspNetCore.Components*` 제거 → `MudBlazor` 추가.
|
||||
- 렌더 모드 전환: `Program.cs` 의 `AddInteractiveServerComponents`/`AddInteractiveServerRenderMode` → `AddInteractiveWebAssemblyComponents`/`AddInteractiveWebAssemblyRenderMode`, 클라이언트 프로젝트(`QuantEngine.Web.Client`) 분리.
|
||||
- `App.razor`: Fluent CSS/JS·`FluentDesignSystemProvider` 제거 → MudBlazor `<MudThemeProvider>`/`<MudDialogProvider>`/`<MudSnackbarProvider>` + `MudBlazor.min.css/js` 삽입.
|
||||
- 전체 `.razor` 컴포넌트의 `Fluent*` → `Mud*` 치환(매핑표는 [CLAUDE.md](../CLAUDE.md) Component Mapping 참조).
|
||||
- API-First: UI 의 직접 DI 호출을 `IXxxBrowserClient`(HTTP) 경유로 전환, `TokenRefreshHandler` 패턴 적용.
|
||||
- **판정:** Fluent UI 패키지/참조 0건, `dotnet build` 오류 0, WASM 로드 후 `/quant/` 및 주요 페이지 정상 렌더, 비-API 라우트 동작 확인.
|
||||
- **주요 파일:** `QuantEngine.Web/QuantEngine.Web.csproj`, `Program.cs`, `Components/App.razor`, `Components/Layout/*.razor`, `Components/Pages/*.razor`, 신규 `QuantEngine.Web.Client/`.
|
||||
- **검증:** `Select-String -Pattern 'Fluent' src/dotnet/QuantEngine.Web -Recurse` → 0건; 브라우저에서 WASM 모드 동작 확인.
|
||||
|
||||
### Track B — 상용 안정화 (SECONDARY, 단일 사용자)
|
||||
|
||||
#### WBS-B1 구성·시크릿 체계화
|
||||
- **목표:** `appsettings.Production.json`(비추적), `IOptions<T>` + 시작 시 구성 검증(fail-fast), 연결 문자열/토큰 환경변수 표준화.
|
||||
- **판정:** 개발/운영 구성 분리, 필수 구성 누락 시 명확 오류로 기동 중단.
|
||||
|
||||
#### WBS-B2 기본 인증 (단일 사용자 보호)
|
||||
- **목표:** 공개 서버 노출 방어용 최소 인증 — 리버스 프록시 Basic Auth 또는 API Key 미들웨어 1종(`/api/*`·UI 보호). 본격 Identity/JWT 는 범위 외.
|
||||
- **판정:** 비인증 요청 401, 인증 요청만 수집/조회 가능.
|
||||
- **파일:** `Program.cs`, `Endpoints/CollectionEndpoints.cs`, Nginx 구성.
|
||||
|
||||
#### WBS-B3 헬스체크·메트릭
|
||||
- **목표:** `MapHealthChecks("/health")`(liveness) + `/health/ready`(PostgreSQL/KIS 토큰 점검), `prometheus-net` 기반 기본 메트릭.
|
||||
- **판정:** 배포 스크립트 헬스체크가 `/health/ready` 사용, 메트릭 엔드포인트 응답.
|
||||
- **파일:** `Program.cs`, `.gitea/workflows/deploy-prod.yml`.
|
||||
|
||||
#### WBS-B4 재시도(Polly)·백그라운드 스케줄러
|
||||
- **목표:** KIS/Naver/Yahoo HTTP 호출에 Polly 재시도·서킷브레이커, 주기적 수집을 `BackgroundService`(또는 systemd timer 연계)로 자동화.
|
||||
- **판정:** 일시적 5xx/네트워크 오류 자동 복구, 정해진 스케줄 무인 수집.
|
||||
- **파일:** `Program.cs`(HttpClient+Polly), 신규 `Application/Services/*BackgroundService.cs`.
|
||||
|
||||
#### WBS-B5 배포 (Docker/CI 게이트)
|
||||
- **목표:** 멀티스테이지 `Dockerfile` + `docker-compose.yml`(app+PostgreSQL), `.gitea` CI 에 `dotnet build`+`dotnet test` 게이트 추가.
|
||||
- **판정:** 컨테이너 로컬 기동 성공, CI 에서 테스트 실패 시 배포 차단.
|
||||
- **파일:** 신규 `Dockerfile`, `docker-compose.yml`, `.gitea/workflows/ci.yml`.
|
||||
|
||||
#### WBS-B6 통합·E2E 테스트 및 커버리지 게이트
|
||||
- **목표:** Testcontainers(PostgreSQL) 통합테스트, KIS→스냅샷→정성매도 E2E, coverlet 커버리지 임계값을 CI 게이트로 연결.
|
||||
- **판정:** E2E 1건 이상 그린, 커버리지 임계 미달 시 CI 실패.
|
||||
- **파일:** `QuantEngine.Core.Tests/`(통합/E2E), `.gitea/workflows/ci.yml`.
|
||||
|
||||
---
|
||||
|
||||
## 5. 개선·보완·고도화 제안 (Track A/B 외 권고)
|
||||
|
||||
- **결정 재현성 감사:** 동일 입력 → 동일 출력 결정론 검증을 CI 상시 게이트로 편입 ([governance/adr/0003-no-llm-numeric-generation.md](../governance/adr/0003-no-llm-numeric-generation.md) 정신 계승).
|
||||
- **캘리브레이션 실증 연계:** [spec/27_bch_calibration_runbook.yaml](../spec/27_bch_calibration_runbook.yaml) 의 `0/190 CALIBRATED` 문제를 마이그레이션과 분리된 데이터 트랙으로 별도 추적(본 WBS 범위 밖, 링크 유지).
|
||||
- **장애 단일점 보강:** Naver Cloudflare 403 폴백 경로를 Yahoo/KIS 다중화로 명문화(WBS-A3 연동).
|
||||
- **운영 가시성:** 구조화 로깅에 상관관계 ID(correlation id) 추가, 수집 실행별 추적 가능화.
|
||||
- **비밀 회전 정책:** KIS appkey/secret, 텔레그램 토큰, DB 비밀번호의 주기적 회전 절차를 [docs/runbook.md](./runbook.md) 에 문서화.
|
||||
- **WBS 표기 정합성 거버넌스:** 본 문서에서 드러난 "완료 표기 vs 실측" 괴리 재발 방지를 위해, 각 WBS 완료 시 **검증 명령 출력 캡처를 증빙으로 첨부**하는 규칙을 강화([AGENTS.md](../AGENTS.md) 의 검증·증빙 강제 원칙 적용).
|
||||
|
||||
---
|
||||
|
||||
## 6. 검증 방법 (각 단계 실행 시)
|
||||
|
||||
- **P0:** `git status` 산출물 미추적 확인, 시크릿 평문 grep 0건, 회전된 자격증명으로 정상 기동.
|
||||
- **Track A:** `cd src/dotnet && dotnet test` 로 패리티/단위/E2E 그린. 패리티 리포트 JSON 을 Python 출력과 diff. 운영 경로 Python 호출 0건.
|
||||
- **Track B:** `curl /health/ready` 200, 비인증 요청 401, `docker compose up` 기동, CI 테스트/커버리지 게이트 동작. Polly 재시도는 장애 주입 테스트로 검증.
|
||||
|
||||
---
|
||||
|
||||
## 7. 실행 순서 요약
|
||||
|
||||
1. **P0 선행 게이트** (WBS-P0.1~P0.3) — 보안·위생 차단. **(기존 10.9 完了 표기 무시, 실측 기준 처리)**
|
||||
2. **Track A** (A1→A2→A3→A4→A5→A6) — 마이그레이션 완성(우선).
|
||||
3. **Track B** (B1~B6) — 단일 사용자 상용 안정화(A 와 병행, B1·B3 조기 착수 권장).
|
||||
@@ -0,0 +1,239 @@
|
||||
using System.Text.Json;
|
||||
using QuantEngine.Core.Interfaces;
|
||||
|
||||
namespace QuantEngine.Application.Services;
|
||||
|
||||
public class DataCollectionService
|
||||
{
|
||||
private readonly IKisApiClient _kisApiClient;
|
||||
private readonly ICollectionRepository _repository;
|
||||
|
||||
public DataCollectionService(
|
||||
IKisApiClient kisApiClient,
|
||||
ICollectionRepository repository)
|
||||
{
|
||||
_kisApiClient = kisApiClient;
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public async Task<CollectionRunResult> RunCollectionAsync(
|
||||
string runId,
|
||||
string account,
|
||||
List<string> tickers)
|
||||
{
|
||||
var result = new CollectionRunResult
|
||||
{
|
||||
RunId = runId,
|
||||
StartedAt = KstNowIso(),
|
||||
Status = "RUNNING"
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
await _repository.SaveRunAsync(new CollectionRunRecord(
|
||||
RunId: runId,
|
||||
Status: "RUNNING",
|
||||
StartedAt: result.StartedAt
|
||||
));
|
||||
|
||||
int successCount = 0;
|
||||
int errorCount = 0;
|
||||
|
||||
foreach (var ticker in tickers)
|
||||
{
|
||||
try
|
||||
{
|
||||
var normalized = await CollectOneAsync(ticker, account);
|
||||
var provenance = new Dictionary<string, object>
|
||||
{
|
||||
{ "ticker", ticker },
|
||||
{ "source", "kis_open_api" }
|
||||
};
|
||||
|
||||
await _repository.SaveSnapshotAsync(new CollectionSnapshotRecord(
|
||||
RunId: runId,
|
||||
DatasetName: "data_feed",
|
||||
Ticker: ticker,
|
||||
SourceName: "kis_open_api",
|
||||
PayloadJson: JsonSerializer.Serialize(normalized),
|
||||
CapturedAt: KstNowIso()
|
||||
));
|
||||
|
||||
successCount++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorCount++;
|
||||
System.Diagnostics.Debug.WriteLine($"Error collecting {ticker}: {ex.Message}");
|
||||
|
||||
await _repository.SaveErrorAsync(new CollectionErrorRecord(
|
||||
RunId: runId,
|
||||
SourceName: "kis_collector",
|
||||
ErrorKind: ex.GetType().Name,
|
||||
ErrorMessage: ex.Message,
|
||||
Ticker: ticker
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
var finishedAt = KstNowIso();
|
||||
await _repository.UpdateRunStatusAsync(
|
||||
runId,
|
||||
errorCount == 0 ? "COMPLETED" : "COMPLETED_WITH_ERRORS",
|
||||
finishedAt,
|
||||
successCount,
|
||||
errorCount
|
||||
);
|
||||
|
||||
result.Status = errorCount == 0 ? "COMPLETED" : "COMPLETED_WITH_ERRORS";
|
||||
result.FinishedAt = finishedAt;
|
||||
result.SuccessCount = successCount;
|
||||
result.ErrorCount = errorCount;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"Fatal error in collection run {runId}: {ex}");
|
||||
await _repository.UpdateRunStatusAsync(runId, "FAILED", KstNowIso());
|
||||
result.Status = "FAILED";
|
||||
result.ErrorMessage = ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<Dictionary<string, object>> CollectOneAsync(string ticker, string account)
|
||||
{
|
||||
var normalized = new Dictionary<string, object> { { "ticker", ticker } };
|
||||
|
||||
try
|
||||
{
|
||||
var price = await _kisApiClient.GetCurrentPriceAsync(ticker, account);
|
||||
normalized["current_price"] = CoerceFloat(FindFirstValue(price, "stck_prpr", "stck_clpr", "close"));
|
||||
normalized["open"] = CoerceFloat(FindFirstValue(price, "stck_oprc", "open"));
|
||||
normalized["high"] = CoerceFloat(FindFirstValue(price, "stck_hgpr", "high"));
|
||||
normalized["low"] = CoerceFloat(FindFirstValue(price, "stck_lwpr", "low"));
|
||||
normalized["prev_close"] = CoerceFloat(FindFirstValue(price, "prdy_vrss"));
|
||||
normalized["volume"] = CoerceFloat(FindFirstValue(price, "acml_vol", "volume"));
|
||||
normalized["change_pct"] = CoerceFloat(FindFirstValue(price, "prdy_ctrt"));
|
||||
normalized["price_status"] = "OK";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
normalized["price_status"] = "ERROR";
|
||||
normalized["price_error"] = ex.Message;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var orderbook = await _kisApiClient.GetAskingPrice10LevelAsync(ticker, account);
|
||||
var output1 = ExtractObject(orderbook, "output1");
|
||||
normalized["ask_1"] = CoerceFloat(FindFirstValue(output1, "askp1"));
|
||||
normalized["bid_1"] = CoerceFloat(FindFirstValue(output1, "bidp1"));
|
||||
normalized["orderbook_status"] = "OK";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
normalized["orderbook_status"] = "ERROR";
|
||||
normalized["orderbook_error"] = ex.Message;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var start = DateTime.Now.AddDays(-10).ToString("yyyyMMdd");
|
||||
var end = DateTime.Now.ToString("yyyyMMdd");
|
||||
var shortSale = await _kisApiClient.GetDailyShortSaleAsync(ticker, start, end, account);
|
||||
var rows = ExtractArray(shortSale, "output2");
|
||||
if (rows.Count > 0 && rows[0] is Dictionary<string, object> latest)
|
||||
{
|
||||
normalized["short_turnover_share"] = CoerceFloat(latest.GetValueOrDefault("ssts_vol_rlim"));
|
||||
}
|
||||
normalized["short_sale_status"] = "OK";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
normalized["short_sale_status"] = "ERROR";
|
||||
normalized["short_sale_error"] = ex.Message;
|
||||
}
|
||||
|
||||
normalized["collection_as_of"] = KstNowIso();
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private static object? FindFirstValue(Dictionary<string, object> payload, params string[] keys)
|
||||
{
|
||||
var stack = new Stack<object>();
|
||||
stack.Push(payload);
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var item = stack.Pop();
|
||||
if (item is Dictionary<string, object> dict)
|
||||
{
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (dict.TryGetValue(key, out var value) && value != null && !string.IsNullOrEmpty(value.ToString()))
|
||||
return value;
|
||||
}
|
||||
foreach (var value in dict.Values)
|
||||
if (value != null) stack.Push(value);
|
||||
}
|
||||
else if (item is JsonElement elem && elem.ValueKind == System.Text.Json.JsonValueKind.Object)
|
||||
{
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (elem.TryGetProperty(key, out var prop) && prop.ValueKind != System.Text.Json.JsonValueKind.Null)
|
||||
return prop;
|
||||
}
|
||||
foreach (var prop in elem.EnumerateObject())
|
||||
stack.Push(prop.Value);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static double? CoerceFloat(object? value)
|
||||
{
|
||||
if (value == null || string.IsNullOrEmpty(value.ToString()))
|
||||
return null;
|
||||
try
|
||||
{
|
||||
var str = value.ToString()?.Replace(",", "").Replace("%", "") ?? "";
|
||||
return double.TryParse(str, out var d) ? d : null;
|
||||
}
|
||||
catch { return null; }
|
||||
}
|
||||
|
||||
private static Dictionary<string, object> ExtractObject(Dictionary<string, object> payload, string key)
|
||||
{
|
||||
if (payload.TryGetValue(key, out var value) && value is Dictionary<string, object> dict)
|
||||
return dict;
|
||||
if (value is JsonElement elem && elem.ValueKind == System.Text.Json.JsonValueKind.Object)
|
||||
return JsonSerializer.Deserialize<Dictionary<string, object>>(elem.GetRawText()) ?? new();
|
||||
return new();
|
||||
}
|
||||
|
||||
private static List<object> ExtractArray(Dictionary<string, object> payload, string key)
|
||||
{
|
||||
if (payload.TryGetValue(key, out var value))
|
||||
{
|
||||
if (value is List<object> list) return list;
|
||||
if (value is JsonElement elem && elem.ValueKind == System.Text.Json.JsonValueKind.Array)
|
||||
return JsonSerializer.Deserialize<List<object>>(elem.GetRawText()) ?? new();
|
||||
}
|
||||
return new();
|
||||
}
|
||||
|
||||
private static string KstNowIso() =>
|
||||
DateTime.Now.ToString("o");
|
||||
}
|
||||
|
||||
public class CollectionRunResult
|
||||
{
|
||||
public string RunId { get; set; } = "";
|
||||
public string Status { get; set; } = "";
|
||||
public string StartedAt { get; set; } = "";
|
||||
public string? FinishedAt { get; set; }
|
||||
public int SuccessCount { get; set; }
|
||||
public int ErrorCount { get; set; }
|
||||
public string? ErrorMessage { get; set; }
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
// <auto-generated/>
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.IO;
|
||||
global using System.Linq;
|
||||
global using System.Net.Http;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
BIN
Binary file not shown.
-698
@@ -1,698 +0,0 @@
|
||||
{
|
||||
"format": 1,
|
||||
"restore": {
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj",
|
||||
"projectName": "QuantEngine.Application",
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj",
|
||||
"packagesPath": "D:\\DevCache\\nuget-packages",
|
||||
"outputPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages",
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\kjh20\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net10.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"C:\\Program Files\\dotnet\\library-packs": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj": {
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "all"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.300"
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.301/PortableRuntimeIdentifierGraph.json",
|
||||
"packagesToPrune": {
|
||||
"Microsoft.CSharp": "(,4.7.32767]",
|
||||
"Microsoft.VisualBasic": "(,10.4.32767]",
|
||||
"Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"Microsoft.Win32.Registry": "(,5.0.32767]",
|
||||
"runtime.any.System.Collections": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.any.System.IO": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.aot.System.Collections": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.aot.System.IO": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Console": "(,4.3.32767]",
|
||||
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Console": "(,4.3.32767]",
|
||||
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"System.AppContext": "(,4.3.32767]",
|
||||
"System.Buffers": "(,5.0.32767]",
|
||||
"System.Collections": "(,4.3.32767]",
|
||||
"System.Collections.Concurrent": "(,4.3.32767]",
|
||||
"System.Collections.Immutable": "(,10.0.32767]",
|
||||
"System.Collections.NonGeneric": "(,4.3.32767]",
|
||||
"System.Collections.Specialized": "(,4.3.32767]",
|
||||
"System.ComponentModel": "(,4.3.32767]",
|
||||
"System.ComponentModel.Annotations": "(,4.3.32767]",
|
||||
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
|
||||
"System.ComponentModel.Primitives": "(,4.3.32767]",
|
||||
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
|
||||
"System.Console": "(,4.3.32767]",
|
||||
"System.Data.Common": "(,4.3.32767]",
|
||||
"System.Data.DataSetExtensions": "(,4.4.32767]",
|
||||
"System.Diagnostics.Contracts": "(,4.3.32767]",
|
||||
"System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"System.Diagnostics.DiagnosticSource": "(,10.0.32767]",
|
||||
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
|
||||
"System.Diagnostics.Process": "(,4.3.32767]",
|
||||
"System.Diagnostics.StackTrace": "(,4.3.32767]",
|
||||
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"System.Diagnostics.TraceSource": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"System.Drawing.Primitives": "(,4.3.32767]",
|
||||
"System.Dynamic.Runtime": "(,4.3.32767]",
|
||||
"System.Formats.Asn1": "(,10.0.32767]",
|
||||
"System.Formats.Tar": "(,10.0.32767]",
|
||||
"System.Globalization": "(,4.3.32767]",
|
||||
"System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"System.Globalization.Extensions": "(,4.3.32767]",
|
||||
"System.IO": "(,4.3.32767]",
|
||||
"System.IO.Compression": "(,4.3.32767]",
|
||||
"System.IO.Compression.ZipFile": "(,4.3.32767]",
|
||||
"System.IO.FileSystem": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
|
||||
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
|
||||
"System.IO.IsolatedStorage": "(,4.3.32767]",
|
||||
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
|
||||
"System.IO.Pipelines": "(,10.0.32767]",
|
||||
"System.IO.Pipes": "(,4.3.32767]",
|
||||
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
|
||||
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
|
||||
"System.Linq": "(,4.3.32767]",
|
||||
"System.Linq.AsyncEnumerable": "(,10.0.32767]",
|
||||
"System.Linq.Expressions": "(,4.3.32767]",
|
||||
"System.Linq.Parallel": "(,4.3.32767]",
|
||||
"System.Linq.Queryable": "(,4.3.32767]",
|
||||
"System.Memory": "(,5.0.32767]",
|
||||
"System.Net.Http": "(,4.3.32767]",
|
||||
"System.Net.Http.Json": "(,10.0.32767]",
|
||||
"System.Net.NameResolution": "(,4.3.32767]",
|
||||
"System.Net.NetworkInformation": "(,4.3.32767]",
|
||||
"System.Net.Ping": "(,4.3.32767]",
|
||||
"System.Net.Primitives": "(,4.3.32767]",
|
||||
"System.Net.Requests": "(,4.3.32767]",
|
||||
"System.Net.Security": "(,4.3.32767]",
|
||||
"System.Net.ServerSentEvents": "(,10.0.32767]",
|
||||
"System.Net.Sockets": "(,4.3.32767]",
|
||||
"System.Net.WebHeaderCollection": "(,4.3.32767]",
|
||||
"System.Net.WebSockets": "(,4.3.32767]",
|
||||
"System.Net.WebSockets.Client": "(,4.3.32767]",
|
||||
"System.Numerics.Vectors": "(,5.0.32767]",
|
||||
"System.ObjectModel": "(,4.3.32767]",
|
||||
"System.Private.DataContractSerialization": "(,4.3.32767]",
|
||||
"System.Private.Uri": "(,4.3.32767]",
|
||||
"System.Reflection": "(,4.3.32767]",
|
||||
"System.Reflection.DispatchProxy": "(,6.0.32767]",
|
||||
"System.Reflection.Emit": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
|
||||
"System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"System.Reflection.Metadata": "(,10.0.32767]",
|
||||
"System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"System.Reflection.TypeExtensions": "(,4.3.32767]",
|
||||
"System.Resources.Reader": "(,4.3.32767]",
|
||||
"System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"System.Resources.Writer": "(,4.3.32767]",
|
||||
"System.Runtime": "(,4.3.32767]",
|
||||
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
|
||||
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
|
||||
"System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"System.Runtime.Handles": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
|
||||
"System.Runtime.Loader": "(,4.3.32767]",
|
||||
"System.Runtime.Numerics": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Json": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
|
||||
"System.Security.AccessControl": "(,6.0.32767]",
|
||||
"System.Security.Claims": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Cng": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Csp": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
|
||||
"System.Security.Principal": "(,4.3.32767]",
|
||||
"System.Security.Principal.Windows": "(,5.0.32767]",
|
||||
"System.Security.SecureString": "(,4.3.32767]",
|
||||
"System.Text.Encoding": "(,4.3.32767]",
|
||||
"System.Text.Encoding.CodePages": "(,10.0.32767]",
|
||||
"System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"System.Text.Encodings.Web": "(,10.0.32767]",
|
||||
"System.Text.Json": "(,10.0.32767]",
|
||||
"System.Text.RegularExpressions": "(,4.3.32767]",
|
||||
"System.Threading": "(,4.3.32767]",
|
||||
"System.Threading.AccessControl": "(,10.0.32767]",
|
||||
"System.Threading.Channels": "(,10.0.32767]",
|
||||
"System.Threading.Overlapped": "(,4.3.32767]",
|
||||
"System.Threading.Tasks": "(,4.3.32767]",
|
||||
"System.Threading.Tasks.Dataflow": "(,10.0.32767]",
|
||||
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
|
||||
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
|
||||
"System.Threading.Thread": "(,4.3.32767]",
|
||||
"System.Threading.ThreadPool": "(,4.3.32767]",
|
||||
"System.Threading.Timer": "(,4.3.32767]",
|
||||
"System.ValueTuple": "(,4.5.32767]",
|
||||
"System.Xml.ReaderWriter": "(,4.3.32767]",
|
||||
"System.Xml.XDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlSerializer": "(,4.3.32767]",
|
||||
"System.Xml.XPath": "(,4.3.32767]",
|
||||
"System.Xml.XPath.XDocument": "(,5.0.32767]"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj",
|
||||
"projectName": "QuantEngine.Core",
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj",
|
||||
"packagesPath": "D:\\DevCache\\nuget-packages",
|
||||
"outputPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages",
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\kjh20\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net10.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"C:\\Program Files\\dotnet\\library-packs": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "all"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.300"
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.301/PortableRuntimeIdentifierGraph.json",
|
||||
"packagesToPrune": {
|
||||
"Microsoft.CSharp": "(,4.7.32767]",
|
||||
"Microsoft.VisualBasic": "(,10.4.32767]",
|
||||
"Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"Microsoft.Win32.Registry": "(,5.0.32767]",
|
||||
"runtime.any.System.Collections": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.any.System.IO": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.aot.System.Collections": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.aot.System.IO": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Console": "(,4.3.32767]",
|
||||
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Console": "(,4.3.32767]",
|
||||
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"System.AppContext": "(,4.3.32767]",
|
||||
"System.Buffers": "(,5.0.32767]",
|
||||
"System.Collections": "(,4.3.32767]",
|
||||
"System.Collections.Concurrent": "(,4.3.32767]",
|
||||
"System.Collections.Immutable": "(,10.0.32767]",
|
||||
"System.Collections.NonGeneric": "(,4.3.32767]",
|
||||
"System.Collections.Specialized": "(,4.3.32767]",
|
||||
"System.ComponentModel": "(,4.3.32767]",
|
||||
"System.ComponentModel.Annotations": "(,4.3.32767]",
|
||||
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
|
||||
"System.ComponentModel.Primitives": "(,4.3.32767]",
|
||||
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
|
||||
"System.Console": "(,4.3.32767]",
|
||||
"System.Data.Common": "(,4.3.32767]",
|
||||
"System.Data.DataSetExtensions": "(,4.4.32767]",
|
||||
"System.Diagnostics.Contracts": "(,4.3.32767]",
|
||||
"System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"System.Diagnostics.DiagnosticSource": "(,10.0.32767]",
|
||||
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
|
||||
"System.Diagnostics.Process": "(,4.3.32767]",
|
||||
"System.Diagnostics.StackTrace": "(,4.3.32767]",
|
||||
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"System.Diagnostics.TraceSource": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"System.Drawing.Primitives": "(,4.3.32767]",
|
||||
"System.Dynamic.Runtime": "(,4.3.32767]",
|
||||
"System.Formats.Asn1": "(,10.0.32767]",
|
||||
"System.Formats.Tar": "(,10.0.32767]",
|
||||
"System.Globalization": "(,4.3.32767]",
|
||||
"System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"System.Globalization.Extensions": "(,4.3.32767]",
|
||||
"System.IO": "(,4.3.32767]",
|
||||
"System.IO.Compression": "(,4.3.32767]",
|
||||
"System.IO.Compression.ZipFile": "(,4.3.32767]",
|
||||
"System.IO.FileSystem": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
|
||||
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
|
||||
"System.IO.IsolatedStorage": "(,4.3.32767]",
|
||||
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
|
||||
"System.IO.Pipelines": "(,10.0.32767]",
|
||||
"System.IO.Pipes": "(,4.3.32767]",
|
||||
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
|
||||
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
|
||||
"System.Linq": "(,4.3.32767]",
|
||||
"System.Linq.AsyncEnumerable": "(,10.0.32767]",
|
||||
"System.Linq.Expressions": "(,4.3.32767]",
|
||||
"System.Linq.Parallel": "(,4.3.32767]",
|
||||
"System.Linq.Queryable": "(,4.3.32767]",
|
||||
"System.Memory": "(,5.0.32767]",
|
||||
"System.Net.Http": "(,4.3.32767]",
|
||||
"System.Net.Http.Json": "(,10.0.32767]",
|
||||
"System.Net.NameResolution": "(,4.3.32767]",
|
||||
"System.Net.NetworkInformation": "(,4.3.32767]",
|
||||
"System.Net.Ping": "(,4.3.32767]",
|
||||
"System.Net.Primitives": "(,4.3.32767]",
|
||||
"System.Net.Requests": "(,4.3.32767]",
|
||||
"System.Net.Security": "(,4.3.32767]",
|
||||
"System.Net.ServerSentEvents": "(,10.0.32767]",
|
||||
"System.Net.Sockets": "(,4.3.32767]",
|
||||
"System.Net.WebHeaderCollection": "(,4.3.32767]",
|
||||
"System.Net.WebSockets": "(,4.3.32767]",
|
||||
"System.Net.WebSockets.Client": "(,4.3.32767]",
|
||||
"System.Numerics.Vectors": "(,5.0.32767]",
|
||||
"System.ObjectModel": "(,4.3.32767]",
|
||||
"System.Private.DataContractSerialization": "(,4.3.32767]",
|
||||
"System.Private.Uri": "(,4.3.32767]",
|
||||
"System.Reflection": "(,4.3.32767]",
|
||||
"System.Reflection.DispatchProxy": "(,6.0.32767]",
|
||||
"System.Reflection.Emit": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
|
||||
"System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"System.Reflection.Metadata": "(,10.0.32767]",
|
||||
"System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"System.Reflection.TypeExtensions": "(,4.3.32767]",
|
||||
"System.Resources.Reader": "(,4.3.32767]",
|
||||
"System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"System.Resources.Writer": "(,4.3.32767]",
|
||||
"System.Runtime": "(,4.3.32767]",
|
||||
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
|
||||
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
|
||||
"System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"System.Runtime.Handles": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
|
||||
"System.Runtime.Loader": "(,4.3.32767]",
|
||||
"System.Runtime.Numerics": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Json": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
|
||||
"System.Security.AccessControl": "(,6.0.32767]",
|
||||
"System.Security.Claims": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Cng": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Csp": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
|
||||
"System.Security.Principal": "(,4.3.32767]",
|
||||
"System.Security.Principal.Windows": "(,5.0.32767]",
|
||||
"System.Security.SecureString": "(,4.3.32767]",
|
||||
"System.Text.Encoding": "(,4.3.32767]",
|
||||
"System.Text.Encoding.CodePages": "(,10.0.32767]",
|
||||
"System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"System.Text.Encodings.Web": "(,10.0.32767]",
|
||||
"System.Text.Json": "(,10.0.32767]",
|
||||
"System.Text.RegularExpressions": "(,4.3.32767]",
|
||||
"System.Threading": "(,4.3.32767]",
|
||||
"System.Threading.AccessControl": "(,10.0.32767]",
|
||||
"System.Threading.Channels": "(,10.0.32767]",
|
||||
"System.Threading.Overlapped": "(,4.3.32767]",
|
||||
"System.Threading.Tasks": "(,4.3.32767]",
|
||||
"System.Threading.Tasks.Dataflow": "(,10.0.32767]",
|
||||
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
|
||||
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
|
||||
"System.Threading.Thread": "(,4.3.32767]",
|
||||
"System.Threading.ThreadPool": "(,4.3.32767]",
|
||||
"System.Threading.Timer": "(,4.3.32767]",
|
||||
"System.ValueTuple": "(,4.5.32767]",
|
||||
"System.Xml.ReaderWriter": "(,4.3.32767]",
|
||||
"System.Xml.XDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlSerializer": "(,4.3.32767]",
|
||||
"System.Xml.XPath": "(,4.3.32767]",
|
||||
"System.Xml.XPath.XDocument": "(,5.0.32767]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">D:\DevCache\nuget-packages</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">D:\DevCache\nuget-packages;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages;C:\Program Files\dotnet\sdk\NuGetFallbackFolder</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="D:\DevCache\nuget-packages\" />
|
||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
||||
<SourceRoot Include="C:\Program Files\dotnet\sdk\NuGetFallbackFolder\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
|
||||
@@ -1,381 +0,0 @@
|
||||
{
|
||||
"version": 4,
|
||||
"targets": {
|
||||
"net10.0": {
|
||||
"QuantEngine.Core/1.0.0": {
|
||||
"type": "project",
|
||||
"framework": ".NETCoreApp,Version=v10.0",
|
||||
"compile": {
|
||||
"bin/placeholder/QuantEngine.Core.dll": {}
|
||||
},
|
||||
"runtime": {
|
||||
"bin/placeholder/QuantEngine.Core.dll": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"QuantEngine.Core/1.0.0": {
|
||||
"type": "project",
|
||||
"path": "../QuantEngine.Core/QuantEngine.Core.csproj",
|
||||
"msbuildProject": "../QuantEngine.Core/QuantEngine.Core.csproj"
|
||||
}
|
||||
},
|
||||
"projectFileDependencyGroups": {
|
||||
"net10.0": [
|
||||
"QuantEngine.Core >= 1.0.0"
|
||||
]
|
||||
},
|
||||
"packageFolders": {
|
||||
"D:\\DevCache\\nuget-packages": {},
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {},
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder": {}
|
||||
},
|
||||
"project": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj",
|
||||
"projectName": "QuantEngine.Application",
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj",
|
||||
"packagesPath": "D:\\DevCache\\nuget-packages",
|
||||
"outputPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages",
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\kjh20\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net10.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"C:\\Program Files\\dotnet\\library-packs": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj": {
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "all"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.300"
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.301/PortableRuntimeIdentifierGraph.json",
|
||||
"packagesToPrune": {
|
||||
"Microsoft.CSharp": "(,4.7.32767]",
|
||||
"Microsoft.VisualBasic": "(,10.4.32767]",
|
||||
"Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"Microsoft.Win32.Registry": "(,5.0.32767]",
|
||||
"runtime.any.System.Collections": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.any.System.IO": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.aot.System.Collections": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.aot.System.IO": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Console": "(,4.3.32767]",
|
||||
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Console": "(,4.3.32767]",
|
||||
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"System.AppContext": "(,4.3.32767]",
|
||||
"System.Buffers": "(,5.0.32767]",
|
||||
"System.Collections": "(,4.3.32767]",
|
||||
"System.Collections.Concurrent": "(,4.3.32767]",
|
||||
"System.Collections.Immutable": "(,10.0.32767]",
|
||||
"System.Collections.NonGeneric": "(,4.3.32767]",
|
||||
"System.Collections.Specialized": "(,4.3.32767]",
|
||||
"System.ComponentModel": "(,4.3.32767]",
|
||||
"System.ComponentModel.Annotations": "(,4.3.32767]",
|
||||
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
|
||||
"System.ComponentModel.Primitives": "(,4.3.32767]",
|
||||
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
|
||||
"System.Console": "(,4.3.32767]",
|
||||
"System.Data.Common": "(,4.3.32767]",
|
||||
"System.Data.DataSetExtensions": "(,4.4.32767]",
|
||||
"System.Diagnostics.Contracts": "(,4.3.32767]",
|
||||
"System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"System.Diagnostics.DiagnosticSource": "(,10.0.32767]",
|
||||
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
|
||||
"System.Diagnostics.Process": "(,4.3.32767]",
|
||||
"System.Diagnostics.StackTrace": "(,4.3.32767]",
|
||||
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"System.Diagnostics.TraceSource": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"System.Drawing.Primitives": "(,4.3.32767]",
|
||||
"System.Dynamic.Runtime": "(,4.3.32767]",
|
||||
"System.Formats.Asn1": "(,10.0.32767]",
|
||||
"System.Formats.Tar": "(,10.0.32767]",
|
||||
"System.Globalization": "(,4.3.32767]",
|
||||
"System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"System.Globalization.Extensions": "(,4.3.32767]",
|
||||
"System.IO": "(,4.3.32767]",
|
||||
"System.IO.Compression": "(,4.3.32767]",
|
||||
"System.IO.Compression.ZipFile": "(,4.3.32767]",
|
||||
"System.IO.FileSystem": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
|
||||
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
|
||||
"System.IO.IsolatedStorage": "(,4.3.32767]",
|
||||
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
|
||||
"System.IO.Pipelines": "(,10.0.32767]",
|
||||
"System.IO.Pipes": "(,4.3.32767]",
|
||||
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
|
||||
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
|
||||
"System.Linq": "(,4.3.32767]",
|
||||
"System.Linq.AsyncEnumerable": "(,10.0.32767]",
|
||||
"System.Linq.Expressions": "(,4.3.32767]",
|
||||
"System.Linq.Parallel": "(,4.3.32767]",
|
||||
"System.Linq.Queryable": "(,4.3.32767]",
|
||||
"System.Memory": "(,5.0.32767]",
|
||||
"System.Net.Http": "(,4.3.32767]",
|
||||
"System.Net.Http.Json": "(,10.0.32767]",
|
||||
"System.Net.NameResolution": "(,4.3.32767]",
|
||||
"System.Net.NetworkInformation": "(,4.3.32767]",
|
||||
"System.Net.Ping": "(,4.3.32767]",
|
||||
"System.Net.Primitives": "(,4.3.32767]",
|
||||
"System.Net.Requests": "(,4.3.32767]",
|
||||
"System.Net.Security": "(,4.3.32767]",
|
||||
"System.Net.ServerSentEvents": "(,10.0.32767]",
|
||||
"System.Net.Sockets": "(,4.3.32767]",
|
||||
"System.Net.WebHeaderCollection": "(,4.3.32767]",
|
||||
"System.Net.WebSockets": "(,4.3.32767]",
|
||||
"System.Net.WebSockets.Client": "(,4.3.32767]",
|
||||
"System.Numerics.Vectors": "(,5.0.32767]",
|
||||
"System.ObjectModel": "(,4.3.32767]",
|
||||
"System.Private.DataContractSerialization": "(,4.3.32767]",
|
||||
"System.Private.Uri": "(,4.3.32767]",
|
||||
"System.Reflection": "(,4.3.32767]",
|
||||
"System.Reflection.DispatchProxy": "(,6.0.32767]",
|
||||
"System.Reflection.Emit": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
|
||||
"System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"System.Reflection.Metadata": "(,10.0.32767]",
|
||||
"System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"System.Reflection.TypeExtensions": "(,4.3.32767]",
|
||||
"System.Resources.Reader": "(,4.3.32767]",
|
||||
"System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"System.Resources.Writer": "(,4.3.32767]",
|
||||
"System.Runtime": "(,4.3.32767]",
|
||||
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
|
||||
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
|
||||
"System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"System.Runtime.Handles": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
|
||||
"System.Runtime.Loader": "(,4.3.32767]",
|
||||
"System.Runtime.Numerics": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Json": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
|
||||
"System.Security.AccessControl": "(,6.0.32767]",
|
||||
"System.Security.Claims": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Cng": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Csp": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
|
||||
"System.Security.Principal": "(,4.3.32767]",
|
||||
"System.Security.Principal.Windows": "(,5.0.32767]",
|
||||
"System.Security.SecureString": "(,4.3.32767]",
|
||||
"System.Text.Encoding": "(,4.3.32767]",
|
||||
"System.Text.Encoding.CodePages": "(,10.0.32767]",
|
||||
"System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"System.Text.Encodings.Web": "(,10.0.32767]",
|
||||
"System.Text.Json": "(,10.0.32767]",
|
||||
"System.Text.RegularExpressions": "(,4.3.32767]",
|
||||
"System.Threading": "(,4.3.32767]",
|
||||
"System.Threading.AccessControl": "(,10.0.32767]",
|
||||
"System.Threading.Channels": "(,10.0.32767]",
|
||||
"System.Threading.Overlapped": "(,4.3.32767]",
|
||||
"System.Threading.Tasks": "(,4.3.32767]",
|
||||
"System.Threading.Tasks.Dataflow": "(,10.0.32767]",
|
||||
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
|
||||
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
|
||||
"System.Threading.Thread": "(,4.3.32767]",
|
||||
"System.Threading.ThreadPool": "(,4.3.32767]",
|
||||
"System.Threading.Timer": "(,4.3.32767]",
|
||||
"System.ValueTuple": "(,4.5.32767]",
|
||||
"System.Xml.ReaderWriter": "(,4.3.32767]",
|
||||
"System.Xml.XDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlSerializer": "(,4.3.32767]",
|
||||
"System.Xml.XPath": "(,4.3.32767]",
|
||||
"System.Xml.XPath.XDocument": "(,5.0.32767]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "fHUX04f/fhA=",
|
||||
"success": true,
|
||||
"projectFilePath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj",
|
||||
"expectedPackageFiles": [],
|
||||
"logs": []
|
||||
}
|
||||
@@ -123,6 +123,12 @@ public class ApplicationServiceTests
|
||||
public (string Domain, string TargetRef)? LastReleasedLock { get; private set; }
|
||||
|
||||
public Task<IEnumerable<Setting>> GetSettingsAsync() => Task.FromResult(Enumerable.Empty<Setting>());
|
||||
public Task<IEnumerable<WorkspaceAccount>> GetAccountsAsync() => Task.FromResult(Enumerable.Empty<WorkspaceAccount>());
|
||||
public Task<WorkspaceAccount?> GetAccountByUsernameAsync(string username) => Task.FromResult<WorkspaceAccount?>(null);
|
||||
public Task<bool> UpsertAccountAsync(WorkspaceAccount account) => Task.FromResult(true);
|
||||
public Task<WorkspaceSession?> GetSessionByTokenHashAsync(string tokenHash) => Task.FromResult<WorkspaceSession?>(null);
|
||||
public Task<bool> UpsertSessionAsync(WorkspaceSession session) => Task.FromResult(true);
|
||||
public Task<bool> RevokeSessionAsync(string tokenHash, string revokedAt) => Task.FromResult(true);
|
||||
public Task<Setting?> GetSettingByKeyAsync(string key) => Task.FromResult<Setting?>(null);
|
||||
public Task<bool> UpsertSettingAsync(Setting setting) { LastSetting = setting; return Task.FromResult(true); }
|
||||
public Task<bool> DeleteSettingAsync(string key) => Task.FromResult(true);
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
// <auto-generated/>
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.IO;
|
||||
global using System.Linq;
|
||||
global using System.Net.Http;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
global using Xunit;
|
||||
BIN
Binary file not shown.
-1429
File diff suppressed because it is too large
Load Diff
@@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">D:\DevCache\nuget-packages</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">D:\DevCache\nuget-packages;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages;C:\Program Files\dotnet\sdk\NuGetFallbackFolder</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="D:\DevCache\nuget-packages\" />
|
||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
||||
<SourceRoot Include="C:\Program Files\dotnet\sdk\NuGetFallbackFolder\" />
|
||||
</ItemGroup>
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="$(NuGetPackageRoot)\xunit.runner.visualstudio\3.1.4\build\net8.0\xunit.runner.visualstudio.props" Condition="Exists('$(NuGetPackageRoot)\xunit.runner.visualstudio\3.1.4\build\net8.0\xunit.runner.visualstudio.props')" />
|
||||
<Import Project="$(NuGetPackageRoot)\xunit.core\2.9.3\build\xunit.core.props" Condition="Exists('$(NuGetPackageRoot)\xunit.core\2.9.3\build\xunit.core.props')" />
|
||||
<Import Project="$(NuGetPackageRoot)\microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.props" Condition="Exists('$(NuGetPackageRoot)\microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.props')" />
|
||||
<Import Project="$(NuGetPackageRoot)\microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.props" Condition="Exists('$(NuGetPackageRoot)\microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.props')" />
|
||||
<Import Project="$(NuGetPackageRoot)\microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.props" Condition="Exists('$(NuGetPackageRoot)\microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.props')" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Pkgxunit_analyzers Condition=" '$(Pkgxunit_analyzers)' == '' ">D:\DevCache\nuget-packages\xunit.analyzers\1.18.0</Pkgxunit_analyzers>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="$(NuGetPackageRoot)\xunit.core\2.9.3\build\xunit.core.targets" Condition="Exists('$(NuGetPackageRoot)\xunit.core\2.9.3\build\xunit.core.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)\microsoft.extensions.logging.abstractions\10.0.0\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)\microsoft.extensions.logging.abstractions\10.0.0\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)\microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.targets" Condition="Exists('$(NuGetPackageRoot)\microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)\microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.targets" Condition="Exists('$(NuGetPackageRoot)\microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)\microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.targets" Condition="Exists('$(NuGetPackageRoot)\microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)\coverlet.collector\6.0.4\build\netstandard2.0\coverlet.collector.targets" Condition="Exists('$(NuGetPackageRoot)\coverlet.collector\6.0.4\build\netstandard2.0\coverlet.collector.targets')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "piIGGEWHUs8=",
|
||||
"success": true,
|
||||
"projectFilePath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core.Tests\\QuantEngine.Core.Tests.csproj",
|
||||
"expectedPackageFiles": [
|
||||
"D:\\DevCache\\nuget-packages\\coverlet.collector\\6.0.4\\coverlet.collector.6.0.4.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\dapper\\2.1.79\\dapper.2.1.79.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\microsoft.codecoverage\\17.14.1\\microsoft.codecoverage.17.14.1.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\microsoft.extensions.dependencyinjection.abstractions\\10.0.0\\microsoft.extensions.dependencyinjection.abstractions.10.0.0.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\microsoft.extensions.logging.abstractions\\10.0.0\\microsoft.extensions.logging.abstractions.10.0.0.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\microsoft.net.test.sdk\\17.14.1\\microsoft.net.test.sdk.17.14.1.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\microsoft.testplatform.objectmodel\\17.14.1\\microsoft.testplatform.objectmodel.17.14.1.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\microsoft.testplatform.testhost\\17.14.1\\microsoft.testplatform.testhost.17.14.1.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\newtonsoft.json\\13.0.3\\newtonsoft.json.13.0.3.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\npgsql\\10.0.3\\npgsql.10.0.3.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\xunit\\2.9.3\\xunit.2.9.3.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\xunit.abstractions\\2.0.3\\xunit.abstractions.2.0.3.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\xunit.analyzers\\1.18.0\\xunit.analyzers.1.18.0.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\xunit.assert\\2.9.3\\xunit.assert.2.9.3.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\xunit.core\\2.9.3\\xunit.core.2.9.3.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\xunit.extensibility.core\\2.9.3\\xunit.extensibility.core.2.9.3.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\xunit.extensibility.execution\\2.9.3\\xunit.extensibility.execution.2.9.3.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\xunit.runner.visualstudio\\3.1.4\\xunit.runner.visualstudio.3.1.4.nupkg.sha512"
|
||||
],
|
||||
"logs": []
|
||||
}
|
||||
@@ -6,6 +6,14 @@ namespace QuantEngine.Core.Interfaces
|
||||
{
|
||||
public interface IWorkspaceRepository
|
||||
{
|
||||
// Accounts
|
||||
Task<IEnumerable<WorkspaceAccount>> GetAccountsAsync();
|
||||
Task<WorkspaceAccount?> GetAccountByUsernameAsync(string username);
|
||||
Task<bool> UpsertAccountAsync(WorkspaceAccount account);
|
||||
Task<WorkspaceSession?> GetSessionByTokenHashAsync(string tokenHash);
|
||||
Task<bool> UpsertSessionAsync(WorkspaceSession session);
|
||||
Task<bool> RevokeSessionAsync(string tokenHash, string revokedAt);
|
||||
|
||||
// Settings
|
||||
Task<IEnumerable<Setting>> GetSettingsAsync();
|
||||
Task<Setting?> GetSettingByKeyAsync(string key);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace QuantEngine.Core.Models
|
||||
{
|
||||
public class WorkspaceAccount
|
||||
{
|
||||
public int Ordinal { get; set; }
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string PasswordHash { get; set; } = string.Empty;
|
||||
public string Role { get; set; } = "Admin";
|
||||
public string IsActive { get; set; } = "true";
|
||||
public string CreatedAt { get; set; } = string.Empty;
|
||||
public string UpdatedAt { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace QuantEngine.Core.Models
|
||||
{
|
||||
public class WorkspaceSession
|
||||
{
|
||||
public string SessionTokenHash { get; set; } = string.Empty;
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string Role { get; set; } = "Admin";
|
||||
public string CreatedAt { get; set; } = string.Empty;
|
||||
public string ExpiresAt { get; set; } = string.Empty;
|
||||
public string? RevokedAt { get; set; }
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
is_global = true
|
||||
build_property.TargetFramework = net10.0
|
||||
build_property.TargetFrameworkIdentifier = .NETCoreApp
|
||||
build_property.TargetFrameworkVersion = v10.0
|
||||
build_property.TargetPlatformMinVersion =
|
||||
build_property.UsingMicrosoftNETSdkWeb =
|
||||
build_property.ProjectTypeGuids =
|
||||
build_property.InvariantGlobalization =
|
||||
build_property.PlatformNeutralAssembly =
|
||||
build_property.EnforceExtendedAnalyzerRules =
|
||||
build_property.EntryPointFilePath =
|
||||
build_property._SupportedPlatformList = Linux,macOS,Windows
|
||||
build_property.RootNamespace = QuantEngine.Core
|
||||
build_property.ProjectDir = C:\Temp\data_feed\src\dotnet\QuantEngine.Core\
|
||||
build_property.EnableComHosting =
|
||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
||||
build_property.EffectiveAnalysisLevelStyle = 10.0
|
||||
build_property.EnableCodeStyleSeverity =
|
||||
@@ -1,8 +0,0 @@
|
||||
// <auto-generated/>
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.IO;
|
||||
global using System.Linq;
|
||||
global using System.Net.Http;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
Binary file not shown.
@@ -1,351 +0,0 @@
|
||||
{
|
||||
"format": 1,
|
||||
"restore": {
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj",
|
||||
"projectName": "QuantEngine.Core",
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj",
|
||||
"packagesPath": "D:\\DevCache\\nuget-packages",
|
||||
"outputPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages",
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\kjh20\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net10.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"C:\\Program Files\\dotnet\\library-packs": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "all"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.300"
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.301/PortableRuntimeIdentifierGraph.json",
|
||||
"packagesToPrune": {
|
||||
"Microsoft.CSharp": "(,4.7.32767]",
|
||||
"Microsoft.VisualBasic": "(,10.4.32767]",
|
||||
"Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"Microsoft.Win32.Registry": "(,5.0.32767]",
|
||||
"runtime.any.System.Collections": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.any.System.IO": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.aot.System.Collections": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.aot.System.IO": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Console": "(,4.3.32767]",
|
||||
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Console": "(,4.3.32767]",
|
||||
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"System.AppContext": "(,4.3.32767]",
|
||||
"System.Buffers": "(,5.0.32767]",
|
||||
"System.Collections": "(,4.3.32767]",
|
||||
"System.Collections.Concurrent": "(,4.3.32767]",
|
||||
"System.Collections.Immutable": "(,10.0.32767]",
|
||||
"System.Collections.NonGeneric": "(,4.3.32767]",
|
||||
"System.Collections.Specialized": "(,4.3.32767]",
|
||||
"System.ComponentModel": "(,4.3.32767]",
|
||||
"System.ComponentModel.Annotations": "(,4.3.32767]",
|
||||
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
|
||||
"System.ComponentModel.Primitives": "(,4.3.32767]",
|
||||
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
|
||||
"System.Console": "(,4.3.32767]",
|
||||
"System.Data.Common": "(,4.3.32767]",
|
||||
"System.Data.DataSetExtensions": "(,4.4.32767]",
|
||||
"System.Diagnostics.Contracts": "(,4.3.32767]",
|
||||
"System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"System.Diagnostics.DiagnosticSource": "(,10.0.32767]",
|
||||
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
|
||||
"System.Diagnostics.Process": "(,4.3.32767]",
|
||||
"System.Diagnostics.StackTrace": "(,4.3.32767]",
|
||||
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"System.Diagnostics.TraceSource": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"System.Drawing.Primitives": "(,4.3.32767]",
|
||||
"System.Dynamic.Runtime": "(,4.3.32767]",
|
||||
"System.Formats.Asn1": "(,10.0.32767]",
|
||||
"System.Formats.Tar": "(,10.0.32767]",
|
||||
"System.Globalization": "(,4.3.32767]",
|
||||
"System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"System.Globalization.Extensions": "(,4.3.32767]",
|
||||
"System.IO": "(,4.3.32767]",
|
||||
"System.IO.Compression": "(,4.3.32767]",
|
||||
"System.IO.Compression.ZipFile": "(,4.3.32767]",
|
||||
"System.IO.FileSystem": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
|
||||
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
|
||||
"System.IO.IsolatedStorage": "(,4.3.32767]",
|
||||
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
|
||||
"System.IO.Pipelines": "(,10.0.32767]",
|
||||
"System.IO.Pipes": "(,4.3.32767]",
|
||||
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
|
||||
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
|
||||
"System.Linq": "(,4.3.32767]",
|
||||
"System.Linq.AsyncEnumerable": "(,10.0.32767]",
|
||||
"System.Linq.Expressions": "(,4.3.32767]",
|
||||
"System.Linq.Parallel": "(,4.3.32767]",
|
||||
"System.Linq.Queryable": "(,4.3.32767]",
|
||||
"System.Memory": "(,5.0.32767]",
|
||||
"System.Net.Http": "(,4.3.32767]",
|
||||
"System.Net.Http.Json": "(,10.0.32767]",
|
||||
"System.Net.NameResolution": "(,4.3.32767]",
|
||||
"System.Net.NetworkInformation": "(,4.3.32767]",
|
||||
"System.Net.Ping": "(,4.3.32767]",
|
||||
"System.Net.Primitives": "(,4.3.32767]",
|
||||
"System.Net.Requests": "(,4.3.32767]",
|
||||
"System.Net.Security": "(,4.3.32767]",
|
||||
"System.Net.ServerSentEvents": "(,10.0.32767]",
|
||||
"System.Net.Sockets": "(,4.3.32767]",
|
||||
"System.Net.WebHeaderCollection": "(,4.3.32767]",
|
||||
"System.Net.WebSockets": "(,4.3.32767]",
|
||||
"System.Net.WebSockets.Client": "(,4.3.32767]",
|
||||
"System.Numerics.Vectors": "(,5.0.32767]",
|
||||
"System.ObjectModel": "(,4.3.32767]",
|
||||
"System.Private.DataContractSerialization": "(,4.3.32767]",
|
||||
"System.Private.Uri": "(,4.3.32767]",
|
||||
"System.Reflection": "(,4.3.32767]",
|
||||
"System.Reflection.DispatchProxy": "(,6.0.32767]",
|
||||
"System.Reflection.Emit": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
|
||||
"System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"System.Reflection.Metadata": "(,10.0.32767]",
|
||||
"System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"System.Reflection.TypeExtensions": "(,4.3.32767]",
|
||||
"System.Resources.Reader": "(,4.3.32767]",
|
||||
"System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"System.Resources.Writer": "(,4.3.32767]",
|
||||
"System.Runtime": "(,4.3.32767]",
|
||||
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
|
||||
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
|
||||
"System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"System.Runtime.Handles": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
|
||||
"System.Runtime.Loader": "(,4.3.32767]",
|
||||
"System.Runtime.Numerics": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Json": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
|
||||
"System.Security.AccessControl": "(,6.0.32767]",
|
||||
"System.Security.Claims": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Cng": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Csp": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
|
||||
"System.Security.Principal": "(,4.3.32767]",
|
||||
"System.Security.Principal.Windows": "(,5.0.32767]",
|
||||
"System.Security.SecureString": "(,4.3.32767]",
|
||||
"System.Text.Encoding": "(,4.3.32767]",
|
||||
"System.Text.Encoding.CodePages": "(,10.0.32767]",
|
||||
"System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"System.Text.Encodings.Web": "(,10.0.32767]",
|
||||
"System.Text.Json": "(,10.0.32767]",
|
||||
"System.Text.RegularExpressions": "(,4.3.32767]",
|
||||
"System.Threading": "(,4.3.32767]",
|
||||
"System.Threading.AccessControl": "(,10.0.32767]",
|
||||
"System.Threading.Channels": "(,10.0.32767]",
|
||||
"System.Threading.Overlapped": "(,4.3.32767]",
|
||||
"System.Threading.Tasks": "(,4.3.32767]",
|
||||
"System.Threading.Tasks.Dataflow": "(,10.0.32767]",
|
||||
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
|
||||
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
|
||||
"System.Threading.Thread": "(,4.3.32767]",
|
||||
"System.Threading.ThreadPool": "(,4.3.32767]",
|
||||
"System.Threading.Timer": "(,4.3.32767]",
|
||||
"System.ValueTuple": "(,4.5.32767]",
|
||||
"System.Xml.ReaderWriter": "(,4.3.32767]",
|
||||
"System.Xml.XDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlSerializer": "(,4.3.32767]",
|
||||
"System.Xml.XPath": "(,4.3.32767]",
|
||||
"System.Xml.XPath.XDocument": "(,5.0.32767]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">D:\DevCache\nuget-packages</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">D:\DevCache\nuget-packages;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages;C:\Program Files\dotnet\sdk\NuGetFallbackFolder</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="D:\DevCache\nuget-packages\" />
|
||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
||||
<SourceRoot Include="C:\Program Files\dotnet\sdk\NuGetFallbackFolder\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
|
||||
@@ -1,358 +0,0 @@
|
||||
{
|
||||
"version": 4,
|
||||
"targets": {
|
||||
"net10.0": {}
|
||||
},
|
||||
"libraries": {},
|
||||
"projectFileDependencyGroups": {
|
||||
"net10.0": []
|
||||
},
|
||||
"packageFolders": {
|
||||
"D:\\DevCache\\nuget-packages": {},
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {},
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder": {}
|
||||
},
|
||||
"project": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj",
|
||||
"projectName": "QuantEngine.Core",
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj",
|
||||
"packagesPath": "D:\\DevCache\\nuget-packages",
|
||||
"outputPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages",
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\kjh20\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net10.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"C:\\Program Files\\dotnet\\library-packs": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "all"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.300"
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.301/PortableRuntimeIdentifierGraph.json",
|
||||
"packagesToPrune": {
|
||||
"Microsoft.CSharp": "(,4.7.32767]",
|
||||
"Microsoft.VisualBasic": "(,10.4.32767]",
|
||||
"Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"Microsoft.Win32.Registry": "(,5.0.32767]",
|
||||
"runtime.any.System.Collections": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.any.System.IO": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.aot.System.Collections": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.aot.System.IO": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Console": "(,4.3.32767]",
|
||||
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Console": "(,4.3.32767]",
|
||||
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"System.AppContext": "(,4.3.32767]",
|
||||
"System.Buffers": "(,5.0.32767]",
|
||||
"System.Collections": "(,4.3.32767]",
|
||||
"System.Collections.Concurrent": "(,4.3.32767]",
|
||||
"System.Collections.Immutable": "(,10.0.32767]",
|
||||
"System.Collections.NonGeneric": "(,4.3.32767]",
|
||||
"System.Collections.Specialized": "(,4.3.32767]",
|
||||
"System.ComponentModel": "(,4.3.32767]",
|
||||
"System.ComponentModel.Annotations": "(,4.3.32767]",
|
||||
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
|
||||
"System.ComponentModel.Primitives": "(,4.3.32767]",
|
||||
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
|
||||
"System.Console": "(,4.3.32767]",
|
||||
"System.Data.Common": "(,4.3.32767]",
|
||||
"System.Data.DataSetExtensions": "(,4.4.32767]",
|
||||
"System.Diagnostics.Contracts": "(,4.3.32767]",
|
||||
"System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"System.Diagnostics.DiagnosticSource": "(,10.0.32767]",
|
||||
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
|
||||
"System.Diagnostics.Process": "(,4.3.32767]",
|
||||
"System.Diagnostics.StackTrace": "(,4.3.32767]",
|
||||
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"System.Diagnostics.TraceSource": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"System.Drawing.Primitives": "(,4.3.32767]",
|
||||
"System.Dynamic.Runtime": "(,4.3.32767]",
|
||||
"System.Formats.Asn1": "(,10.0.32767]",
|
||||
"System.Formats.Tar": "(,10.0.32767]",
|
||||
"System.Globalization": "(,4.3.32767]",
|
||||
"System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"System.Globalization.Extensions": "(,4.3.32767]",
|
||||
"System.IO": "(,4.3.32767]",
|
||||
"System.IO.Compression": "(,4.3.32767]",
|
||||
"System.IO.Compression.ZipFile": "(,4.3.32767]",
|
||||
"System.IO.FileSystem": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
|
||||
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
|
||||
"System.IO.IsolatedStorage": "(,4.3.32767]",
|
||||
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
|
||||
"System.IO.Pipelines": "(,10.0.32767]",
|
||||
"System.IO.Pipes": "(,4.3.32767]",
|
||||
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
|
||||
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
|
||||
"System.Linq": "(,4.3.32767]",
|
||||
"System.Linq.AsyncEnumerable": "(,10.0.32767]",
|
||||
"System.Linq.Expressions": "(,4.3.32767]",
|
||||
"System.Linq.Parallel": "(,4.3.32767]",
|
||||
"System.Linq.Queryable": "(,4.3.32767]",
|
||||
"System.Memory": "(,5.0.32767]",
|
||||
"System.Net.Http": "(,4.3.32767]",
|
||||
"System.Net.Http.Json": "(,10.0.32767]",
|
||||
"System.Net.NameResolution": "(,4.3.32767]",
|
||||
"System.Net.NetworkInformation": "(,4.3.32767]",
|
||||
"System.Net.Ping": "(,4.3.32767]",
|
||||
"System.Net.Primitives": "(,4.3.32767]",
|
||||
"System.Net.Requests": "(,4.3.32767]",
|
||||
"System.Net.Security": "(,4.3.32767]",
|
||||
"System.Net.ServerSentEvents": "(,10.0.32767]",
|
||||
"System.Net.Sockets": "(,4.3.32767]",
|
||||
"System.Net.WebHeaderCollection": "(,4.3.32767]",
|
||||
"System.Net.WebSockets": "(,4.3.32767]",
|
||||
"System.Net.WebSockets.Client": "(,4.3.32767]",
|
||||
"System.Numerics.Vectors": "(,5.0.32767]",
|
||||
"System.ObjectModel": "(,4.3.32767]",
|
||||
"System.Private.DataContractSerialization": "(,4.3.32767]",
|
||||
"System.Private.Uri": "(,4.3.32767]",
|
||||
"System.Reflection": "(,4.3.32767]",
|
||||
"System.Reflection.DispatchProxy": "(,6.0.32767]",
|
||||
"System.Reflection.Emit": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
|
||||
"System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"System.Reflection.Metadata": "(,10.0.32767]",
|
||||
"System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"System.Reflection.TypeExtensions": "(,4.3.32767]",
|
||||
"System.Resources.Reader": "(,4.3.32767]",
|
||||
"System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"System.Resources.Writer": "(,4.3.32767]",
|
||||
"System.Runtime": "(,4.3.32767]",
|
||||
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
|
||||
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
|
||||
"System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"System.Runtime.Handles": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
|
||||
"System.Runtime.Loader": "(,4.3.32767]",
|
||||
"System.Runtime.Numerics": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Json": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
|
||||
"System.Security.AccessControl": "(,6.0.32767]",
|
||||
"System.Security.Claims": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Cng": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Csp": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
|
||||
"System.Security.Principal": "(,4.3.32767]",
|
||||
"System.Security.Principal.Windows": "(,5.0.32767]",
|
||||
"System.Security.SecureString": "(,4.3.32767]",
|
||||
"System.Text.Encoding": "(,4.3.32767]",
|
||||
"System.Text.Encoding.CodePages": "(,10.0.32767]",
|
||||
"System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"System.Text.Encodings.Web": "(,10.0.32767]",
|
||||
"System.Text.Json": "(,10.0.32767]",
|
||||
"System.Text.RegularExpressions": "(,4.3.32767]",
|
||||
"System.Threading": "(,4.3.32767]",
|
||||
"System.Threading.AccessControl": "(,10.0.32767]",
|
||||
"System.Threading.Channels": "(,10.0.32767]",
|
||||
"System.Threading.Overlapped": "(,4.3.32767]",
|
||||
"System.Threading.Tasks": "(,4.3.32767]",
|
||||
"System.Threading.Tasks.Dataflow": "(,10.0.32767]",
|
||||
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
|
||||
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
|
||||
"System.Threading.Thread": "(,4.3.32767]",
|
||||
"System.Threading.ThreadPool": "(,4.3.32767]",
|
||||
"System.Threading.Timer": "(,4.3.32767]",
|
||||
"System.ValueTuple": "(,4.5.32767]",
|
||||
"System.Xml.ReaderWriter": "(,4.3.32767]",
|
||||
"System.Xml.XDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlSerializer": "(,4.3.32767]",
|
||||
"System.Xml.XPath": "(,4.3.32767]",
|
||||
"System.Xml.XPath.XDocument": "(,5.0.32767]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "ZsY9lhMy6SQ=",
|
||||
"success": true,
|
||||
"projectFilePath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj",
|
||||
"expectedPackageFiles": [],
|
||||
"logs": []
|
||||
}
|
||||
@@ -30,6 +30,32 @@ namespace QuantEngine.Infrastructure.Data
|
||||
);
|
||||
");
|
||||
|
||||
// 0b. workspace_account
|
||||
conn.Execute(@"
|
||||
CREATE TABLE IF NOT EXISTS workspace_account (
|
||||
ordinal INT NOT NULL,
|
||||
username TEXT PRIMARY KEY,
|
||||
password_hash TEXT NOT NULL,
|
||||
role TEXT NOT NULL DEFAULT 'Admin',
|
||||
is_active TEXT NOT NULL DEFAULT 'true',
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_workspace_account_active ON workspace_account(is_active, username);
|
||||
");
|
||||
|
||||
conn.Execute(@"
|
||||
CREATE TABLE IF NOT EXISTS workspace_session (
|
||||
session_token_hash TEXT PRIMARY KEY,
|
||||
username TEXT NOT NULL,
|
||||
role TEXT NOT NULL DEFAULT 'Admin',
|
||||
created_at TEXT NOT NULL,
|
||||
expires_at TEXT NOT NULL,
|
||||
revoked_at TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_workspace_session_username ON workspace_session(username, expires_at DESC);
|
||||
");
|
||||
|
||||
// 1. collection_runs
|
||||
conn.Execute(@"
|
||||
CREATE TABLE IF NOT EXISTS collection_runs (
|
||||
@@ -157,6 +183,16 @@ namespace QuantEngine.Infrastructure.Data
|
||||
);
|
||||
");
|
||||
|
||||
conn.Execute(@"
|
||||
INSERT INTO quantengine.workspace_account (
|
||||
ordinal, username, password_hash, role, is_active, created_at, updated_at
|
||||
)
|
||||
SELECT 1, 'admin', '8C6976E5B5410415BDE908BD4DEE15DFB167A9C873FC4BB8A81F6F2AB448A918', 'Admin', 'true', NOW()::text, NOW()::text
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM quantengine.workspace_account WHERE username = 'admin'
|
||||
);
|
||||
");
|
||||
|
||||
// 10. engine_history schema and tables
|
||||
conn.Execute(@"
|
||||
CREATE SCHEMA IF NOT EXISTS engine_history;
|
||||
|
||||
@@ -17,6 +17,89 @@ namespace QuantEngine.Infrastructure.Repositories
|
||||
_connectionFactory = connectionFactory;
|
||||
}
|
||||
|
||||
// Accounts
|
||||
public async Task<IEnumerable<WorkspaceAccount>> GetAccountsAsync()
|
||||
{
|
||||
using var conn = _connectionFactory.CreateConnection();
|
||||
return await conn.QueryAsync<WorkspaceAccount>(@"
|
||||
SELECT ordinal, username as Username, password_hash as PasswordHash, role as Role,
|
||||
is_active as IsActive, created_at as CreatedAt, updated_at as UpdatedAt
|
||||
FROM quantengine.workspace_account
|
||||
ORDER BY ordinal ASC"
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<WorkspaceAccount?> GetAccountByUsernameAsync(string username)
|
||||
{
|
||||
using var conn = _connectionFactory.CreateConnection();
|
||||
return await conn.QueryFirstOrDefaultAsync<WorkspaceAccount>(@"
|
||||
SELECT ordinal, username as Username, password_hash as PasswordHash, role as Role,
|
||||
is_active as IsActive, created_at as CreatedAt, updated_at as UpdatedAt
|
||||
FROM quantengine.workspace_account
|
||||
WHERE username = @Username",
|
||||
new { Username = username }
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<bool> UpsertAccountAsync(WorkspaceAccount account)
|
||||
{
|
||||
using var conn = _connectionFactory.CreateConnection();
|
||||
var affected = await conn.ExecuteAsync(@"
|
||||
INSERT INTO quantengine.workspace_account (ordinal, username, password_hash, role, is_active, created_at, updated_at)
|
||||
VALUES (@Ordinal, @Username, @PasswordHash, @Role, @IsActive, @CreatedAt, @UpdatedAt)
|
||||
ON CONFLICT (username) DO UPDATE SET
|
||||
ordinal = EXCLUDED.ordinal,
|
||||
password_hash = EXCLUDED.password_hash,
|
||||
role = EXCLUDED.role,
|
||||
is_active = EXCLUDED.is_active,
|
||||
updated_at = EXCLUDED.updated_at",
|
||||
account
|
||||
);
|
||||
return affected > 0;
|
||||
}
|
||||
|
||||
public async Task<WorkspaceSession?> GetSessionByTokenHashAsync(string tokenHash)
|
||||
{
|
||||
using var conn = _connectionFactory.CreateConnection();
|
||||
return await conn.QueryFirstOrDefaultAsync<WorkspaceSession>(@"
|
||||
SELECT session_token_hash as SessionTokenHash, username as Username, role as Role,
|
||||
created_at as CreatedAt, expires_at as ExpiresAt, revoked_at as RevokedAt
|
||||
FROM quantengine.workspace_session
|
||||
WHERE session_token_hash = @TokenHash",
|
||||
new { TokenHash = tokenHash }
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<bool> UpsertSessionAsync(WorkspaceSession session)
|
||||
{
|
||||
using var conn = _connectionFactory.CreateConnection();
|
||||
var affected = await conn.ExecuteAsync(@"
|
||||
INSERT INTO quantengine.workspace_session
|
||||
(session_token_hash, username, role, created_at, expires_at, revoked_at)
|
||||
VALUES
|
||||
(@SessionTokenHash, @Username, @Role, @CreatedAt, @ExpiresAt, @RevokedAt)
|
||||
ON CONFLICT (session_token_hash) DO UPDATE SET
|
||||
username = EXCLUDED.username,
|
||||
role = EXCLUDED.role,
|
||||
expires_at = EXCLUDED.expires_at,
|
||||
revoked_at = EXCLUDED.revoked_at",
|
||||
session
|
||||
);
|
||||
return affected > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> RevokeSessionAsync(string tokenHash, string revokedAt)
|
||||
{
|
||||
using var conn = _connectionFactory.CreateConnection();
|
||||
var affected = await conn.ExecuteAsync(@"
|
||||
UPDATE quantengine.workspace_session
|
||||
SET revoked_at = @RevokedAt
|
||||
WHERE session_token_hash = @TokenHash",
|
||||
new { TokenHash = tokenHash, RevokedAt = revokedAt }
|
||||
);
|
||||
return affected > 0;
|
||||
}
|
||||
|
||||
// Settings
|
||||
public async Task<IEnumerable<Setting>> GetSettingsAsync()
|
||||
{
|
||||
|
||||
@@ -174,8 +174,15 @@ public class KisApiClient : IKisApiClient
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var tokenData = await response.Content.ReadFromJsonAsync<Dictionary<string, object>>();
|
||||
var accessToken = tokenData["access_token"]?.ToString() ?? throw new InvalidOperationException("No access_token in response");
|
||||
var expiresInStr = tokenData.ContainsKey("expires_in") ? tokenData["expires_in"]?.ToString() : "86400";
|
||||
if (tokenData == null) throw new InvalidOperationException("Token response body is empty");
|
||||
|
||||
if (!tokenData.TryGetValue("access_token", out var tokenObj) || tokenObj == null)
|
||||
throw new InvalidOperationException("No access_token in response");
|
||||
var accessToken = tokenObj.ToString()!;
|
||||
|
||||
var expiresInStr = tokenData.TryGetValue("expires_in", out var expiresObj) && expiresObj != null
|
||||
? expiresObj.ToString()
|
||||
: "86400";
|
||||
var expiresInSec = int.TryParse(expiresInStr, out var seconds) ? seconds : 86400;
|
||||
var expiresAt = DateTime.UtcNow.AddSeconds(expiresInSec);
|
||||
|
||||
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
// <auto-generated/>
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.IO;
|
||||
global using System.Linq;
|
||||
global using System.Net.Http;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
BIN
Binary file not shown.
-1058
File diff suppressed because it is too large
Load Diff
-17
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">D:\DevCache\nuget-packages</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">D:\DevCache\nuget-packages;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages;C:\Program Files\dotnet\sdk\NuGetFallbackFolder</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="D:\DevCache\nuget-packages\" />
|
||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
||||
<SourceRoot Include="C:\Program Files\dotnet\sdk\NuGetFallbackFolder\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="$(NuGetPackageRoot)\microsoft.extensions.logging.abstractions\10.0.0\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)\microsoft.extensions.logging.abstractions\10.0.0\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,622 +0,0 @@
|
||||
{
|
||||
"version": 4,
|
||||
"targets": {
|
||||
"net10.0": {
|
||||
"Dapper/2.1.79": {
|
||||
"type": "package",
|
||||
"compile": {
|
||||
"lib/net10.0/Dapper.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Dapper.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0": {
|
||||
"type": "package",
|
||||
"compile": {
|
||||
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"buildTransitive/net8.0/_._": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions/10.0.0": {
|
||||
"type": "package",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
|
||||
},
|
||||
"compile": {
|
||||
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets": {}
|
||||
}
|
||||
},
|
||||
"Npgsql/10.0.3": {
|
||||
"type": "package",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "10.0.0"
|
||||
},
|
||||
"compile": {
|
||||
"lib/net10.0/Npgsql.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Npgsql.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
}
|
||||
},
|
||||
"QuantEngine.Application/1.0.0": {
|
||||
"type": "project",
|
||||
"framework": ".NETCoreApp,Version=v10.0",
|
||||
"dependencies": {
|
||||
"QuantEngine.Core": "1.0.0"
|
||||
},
|
||||
"compile": {
|
||||
"bin/placeholder/QuantEngine.Application.dll": {}
|
||||
},
|
||||
"runtime": {
|
||||
"bin/placeholder/QuantEngine.Application.dll": {}
|
||||
}
|
||||
},
|
||||
"QuantEngine.Core/1.0.0": {
|
||||
"type": "project",
|
||||
"framework": ".NETCoreApp,Version=v10.0",
|
||||
"compile": {
|
||||
"bin/placeholder/QuantEngine.Core.dll": {}
|
||||
},
|
||||
"runtime": {
|
||||
"bin/placeholder/QuantEngine.Core.dll": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"Dapper/2.1.79": {
|
||||
"sha512": "8YijbzgTfmqmQOnVNorYM6K++pxqnW3nJ4aC1sRHzxUA2CcuoJ9gsTem3kgBnPRMc38zZHl4Esb6hAezXIEEuw==",
|
||||
"type": "package",
|
||||
"path": "dapper/2.1.79",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"Dapper.png",
|
||||
"dapper.2.1.79.nupkg.sha512",
|
||||
"dapper.nuspec",
|
||||
"lib/net10.0/Dapper.dll",
|
||||
"lib/net10.0/Dapper.xml",
|
||||
"lib/net461/Dapper.dll",
|
||||
"lib/net461/Dapper.xml",
|
||||
"lib/net8.0/Dapper.dll",
|
||||
"lib/net8.0/Dapper.xml",
|
||||
"lib/netstandard2.0/Dapper.dll",
|
||||
"lib/netstandard2.0/Dapper.xml",
|
||||
"readme.md"
|
||||
]
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0": {
|
||||
"sha512": "L3AdmZ1WOK4XXT5YFPEwyt0ep6l8lGIPs7F5OOBZc77Zqeo01Of7XXICy47628sdVl0v/owxYJTe86DTgFwKCA==",
|
||||
"type": "package",
|
||||
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.0",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"Icon.png",
|
||||
"PACKAGE.md",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"buildTransitive/net461/Microsoft.Extensions.DependencyInjection.Abstractions.targets",
|
||||
"buildTransitive/net462/_._",
|
||||
"buildTransitive/net8.0/_._",
|
||||
"buildTransitive/netcoreapp2.0/Microsoft.Extensions.DependencyInjection.Abstractions.targets",
|
||||
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll",
|
||||
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml",
|
||||
"lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll",
|
||||
"lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.xml",
|
||||
"lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll",
|
||||
"lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml",
|
||||
"lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll",
|
||||
"lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml",
|
||||
"lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll",
|
||||
"lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml",
|
||||
"lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll",
|
||||
"lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.xml",
|
||||
"microsoft.extensions.dependencyinjection.abstractions.10.0.0.nupkg.sha512",
|
||||
"microsoft.extensions.dependencyinjection.abstractions.nuspec",
|
||||
"useSharedDesignerContext.txt"
|
||||
]
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions/10.0.0": {
|
||||
"sha512": "FU/IfjDfwaMuKr414SSQNTIti/69bHEMb+QKrskRb26oVqpx3lNFXMjs/RC9ZUuhBhcwDM2BwOgoMw+PZ+beqQ==",
|
||||
"type": "package",
|
||||
"path": "microsoft.extensions.logging.abstractions/10.0.0",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"Icon.png",
|
||||
"PACKAGE.md",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"analyzers/dotnet/roslyn3.11/cs/Microsoft.Extensions.Logging.Generators.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn3.11/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/Microsoft.Extensions.Logging.Generators.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.0/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/Microsoft.Extensions.Logging.Generators.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"analyzers/dotnet/roslyn4.4/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll",
|
||||
"buildTransitive/net461/Microsoft.Extensions.Logging.Abstractions.targets",
|
||||
"buildTransitive/net462/Microsoft.Extensions.Logging.Abstractions.targets",
|
||||
"buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets",
|
||||
"buildTransitive/netcoreapp2.0/Microsoft.Extensions.Logging.Abstractions.targets",
|
||||
"buildTransitive/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.targets",
|
||||
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll",
|
||||
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.xml",
|
||||
"lib/net462/Microsoft.Extensions.Logging.Abstractions.dll",
|
||||
"lib/net462/Microsoft.Extensions.Logging.Abstractions.xml",
|
||||
"lib/net8.0/Microsoft.Extensions.Logging.Abstractions.dll",
|
||||
"lib/net8.0/Microsoft.Extensions.Logging.Abstractions.xml",
|
||||
"lib/net9.0/Microsoft.Extensions.Logging.Abstractions.dll",
|
||||
"lib/net9.0/Microsoft.Extensions.Logging.Abstractions.xml",
|
||||
"lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll",
|
||||
"lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.xml",
|
||||
"microsoft.extensions.logging.abstractions.10.0.0.nupkg.sha512",
|
||||
"microsoft.extensions.logging.abstractions.nuspec",
|
||||
"useSharedDesignerContext.txt"
|
||||
]
|
||||
},
|
||||
"Npgsql/10.0.3": {
|
||||
"sha512": "7nb5YzXuvWWJxB0J8DiyL3we+X4FOctZrt0fIBnucOIaIevFEEwGQVZKtiu9olXdlNAK1eNgqSral6r/jlhI4w==",
|
||||
"type": "package",
|
||||
"path": "npgsql/10.0.3",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"README.md",
|
||||
"lib/net10.0/Npgsql.dll",
|
||||
"lib/net10.0/Npgsql.xml",
|
||||
"lib/net8.0/Npgsql.dll",
|
||||
"lib/net8.0/Npgsql.xml",
|
||||
"lib/net9.0/Npgsql.dll",
|
||||
"lib/net9.0/Npgsql.xml",
|
||||
"npgsql.10.0.3.nupkg.sha512",
|
||||
"npgsql.nuspec",
|
||||
"postgresql.png"
|
||||
]
|
||||
},
|
||||
"QuantEngine.Application/1.0.0": {
|
||||
"type": "project",
|
||||
"path": "../QuantEngine.Application/QuantEngine.Application.csproj",
|
||||
"msbuildProject": "../QuantEngine.Application/QuantEngine.Application.csproj"
|
||||
},
|
||||
"QuantEngine.Core/1.0.0": {
|
||||
"type": "project",
|
||||
"path": "../QuantEngine.Core/QuantEngine.Core.csproj",
|
||||
"msbuildProject": "../QuantEngine.Core/QuantEngine.Core.csproj"
|
||||
}
|
||||
},
|
||||
"projectFileDependencyGroups": {
|
||||
"net10.0": [
|
||||
"Dapper >= 2.1.79",
|
||||
"Npgsql >= 10.0.3",
|
||||
"QuantEngine.Application >= 1.0.0",
|
||||
"QuantEngine.Core >= 1.0.0"
|
||||
]
|
||||
},
|
||||
"packageFolders": {
|
||||
"D:\\DevCache\\nuget-packages": {},
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {},
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder": {}
|
||||
},
|
||||
"project": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Infrastructure\\QuantEngine.Infrastructure.csproj",
|
||||
"projectName": "QuantEngine.Infrastructure",
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Infrastructure\\QuantEngine.Infrastructure.csproj",
|
||||
"packagesPath": "D:\\DevCache\\nuget-packages",
|
||||
"outputPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Infrastructure\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages",
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\kjh20\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net10.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"C:\\Program Files\\dotnet\\library-packs": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj": {
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj"
|
||||
},
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj": {
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "all"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.300"
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"dependencies": {
|
||||
"Dapper": {
|
||||
"target": "Package",
|
||||
"version": "[2.1.79, )"
|
||||
},
|
||||
"Npgsql": {
|
||||
"target": "Package",
|
||||
"version": "[10.0.3, )"
|
||||
}
|
||||
},
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.301/PortableRuntimeIdentifierGraph.json",
|
||||
"packagesToPrune": {
|
||||
"Microsoft.CSharp": "(,4.7.32767]",
|
||||
"Microsoft.VisualBasic": "(,10.4.32767]",
|
||||
"Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"Microsoft.Win32.Registry": "(,5.0.32767]",
|
||||
"runtime.any.System.Collections": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.any.System.IO": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.aot.System.Collections": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.aot.System.IO": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Console": "(,4.3.32767]",
|
||||
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Console": "(,4.3.32767]",
|
||||
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"System.AppContext": "(,4.3.32767]",
|
||||
"System.Buffers": "(,5.0.32767]",
|
||||
"System.Collections": "(,4.3.32767]",
|
||||
"System.Collections.Concurrent": "(,4.3.32767]",
|
||||
"System.Collections.Immutable": "(,10.0.32767]",
|
||||
"System.Collections.NonGeneric": "(,4.3.32767]",
|
||||
"System.Collections.Specialized": "(,4.3.32767]",
|
||||
"System.ComponentModel": "(,4.3.32767]",
|
||||
"System.ComponentModel.Annotations": "(,4.3.32767]",
|
||||
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
|
||||
"System.ComponentModel.Primitives": "(,4.3.32767]",
|
||||
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
|
||||
"System.Console": "(,4.3.32767]",
|
||||
"System.Data.Common": "(,4.3.32767]",
|
||||
"System.Data.DataSetExtensions": "(,4.4.32767]",
|
||||
"System.Diagnostics.Contracts": "(,4.3.32767]",
|
||||
"System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"System.Diagnostics.DiagnosticSource": "(,10.0.32767]",
|
||||
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
|
||||
"System.Diagnostics.Process": "(,4.3.32767]",
|
||||
"System.Diagnostics.StackTrace": "(,4.3.32767]",
|
||||
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"System.Diagnostics.TraceSource": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"System.Drawing.Primitives": "(,4.3.32767]",
|
||||
"System.Dynamic.Runtime": "(,4.3.32767]",
|
||||
"System.Formats.Asn1": "(,10.0.32767]",
|
||||
"System.Formats.Tar": "(,10.0.32767]",
|
||||
"System.Globalization": "(,4.3.32767]",
|
||||
"System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"System.Globalization.Extensions": "(,4.3.32767]",
|
||||
"System.IO": "(,4.3.32767]",
|
||||
"System.IO.Compression": "(,4.3.32767]",
|
||||
"System.IO.Compression.ZipFile": "(,4.3.32767]",
|
||||
"System.IO.FileSystem": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
|
||||
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
|
||||
"System.IO.IsolatedStorage": "(,4.3.32767]",
|
||||
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
|
||||
"System.IO.Pipelines": "(,10.0.32767]",
|
||||
"System.IO.Pipes": "(,4.3.32767]",
|
||||
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
|
||||
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
|
||||
"System.Linq": "(,4.3.32767]",
|
||||
"System.Linq.AsyncEnumerable": "(,10.0.32767]",
|
||||
"System.Linq.Expressions": "(,4.3.32767]",
|
||||
"System.Linq.Parallel": "(,4.3.32767]",
|
||||
"System.Linq.Queryable": "(,4.3.32767]",
|
||||
"System.Memory": "(,5.0.32767]",
|
||||
"System.Net.Http": "(,4.3.32767]",
|
||||
"System.Net.Http.Json": "(,10.0.32767]",
|
||||
"System.Net.NameResolution": "(,4.3.32767]",
|
||||
"System.Net.NetworkInformation": "(,4.3.32767]",
|
||||
"System.Net.Ping": "(,4.3.32767]",
|
||||
"System.Net.Primitives": "(,4.3.32767]",
|
||||
"System.Net.Requests": "(,4.3.32767]",
|
||||
"System.Net.Security": "(,4.3.32767]",
|
||||
"System.Net.ServerSentEvents": "(,10.0.32767]",
|
||||
"System.Net.Sockets": "(,4.3.32767]",
|
||||
"System.Net.WebHeaderCollection": "(,4.3.32767]",
|
||||
"System.Net.WebSockets": "(,4.3.32767]",
|
||||
"System.Net.WebSockets.Client": "(,4.3.32767]",
|
||||
"System.Numerics.Vectors": "(,5.0.32767]",
|
||||
"System.ObjectModel": "(,4.3.32767]",
|
||||
"System.Private.DataContractSerialization": "(,4.3.32767]",
|
||||
"System.Private.Uri": "(,4.3.32767]",
|
||||
"System.Reflection": "(,4.3.32767]",
|
||||
"System.Reflection.DispatchProxy": "(,6.0.32767]",
|
||||
"System.Reflection.Emit": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
|
||||
"System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"System.Reflection.Metadata": "(,10.0.32767]",
|
||||
"System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"System.Reflection.TypeExtensions": "(,4.3.32767]",
|
||||
"System.Resources.Reader": "(,4.3.32767]",
|
||||
"System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"System.Resources.Writer": "(,4.3.32767]",
|
||||
"System.Runtime": "(,4.3.32767]",
|
||||
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
|
||||
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
|
||||
"System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"System.Runtime.Handles": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
|
||||
"System.Runtime.Loader": "(,4.3.32767]",
|
||||
"System.Runtime.Numerics": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Json": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
|
||||
"System.Security.AccessControl": "(,6.0.32767]",
|
||||
"System.Security.Claims": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Cng": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Csp": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
|
||||
"System.Security.Principal": "(,4.3.32767]",
|
||||
"System.Security.Principal.Windows": "(,5.0.32767]",
|
||||
"System.Security.SecureString": "(,4.3.32767]",
|
||||
"System.Text.Encoding": "(,4.3.32767]",
|
||||
"System.Text.Encoding.CodePages": "(,10.0.32767]",
|
||||
"System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"System.Text.Encodings.Web": "(,10.0.32767]",
|
||||
"System.Text.Json": "(,10.0.32767]",
|
||||
"System.Text.RegularExpressions": "(,4.3.32767]",
|
||||
"System.Threading": "(,4.3.32767]",
|
||||
"System.Threading.AccessControl": "(,10.0.32767]",
|
||||
"System.Threading.Channels": "(,10.0.32767]",
|
||||
"System.Threading.Overlapped": "(,4.3.32767]",
|
||||
"System.Threading.Tasks": "(,4.3.32767]",
|
||||
"System.Threading.Tasks.Dataflow": "(,10.0.32767]",
|
||||
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
|
||||
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
|
||||
"System.Threading.Thread": "(,4.3.32767]",
|
||||
"System.Threading.ThreadPool": "(,4.3.32767]",
|
||||
"System.Threading.Timer": "(,4.3.32767]",
|
||||
"System.ValueTuple": "(,4.5.32767]",
|
||||
"System.Xml.ReaderWriter": "(,4.3.32767]",
|
||||
"System.Xml.XDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlSerializer": "(,4.3.32767]",
|
||||
"System.Xml.XPath": "(,4.3.32767]",
|
||||
"System.Xml.XPath.XDocument": "(,5.0.32767]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "KzZeTlTcjPo=",
|
||||
"success": true,
|
||||
"projectFilePath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Infrastructure\\QuantEngine.Infrastructure.csproj",
|
||||
"expectedPackageFiles": [
|
||||
"D:\\DevCache\\nuget-packages\\dapper\\2.1.79\\dapper.2.1.79.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\microsoft.extensions.dependencyinjection.abstractions\\10.0.0\\microsoft.extensions.dependencyinjection.abstractions.10.0.0.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\microsoft.extensions.logging.abstractions\\10.0.0\\microsoft.extensions.logging.abstractions.10.0.0.nupkg.sha512",
|
||||
"D:\\DevCache\\nuget-packages\\npgsql\\10.0.3\\npgsql.10.0.3.nupkg.sha512"
|
||||
],
|
||||
"logs": []
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
// <auto-generated/>
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.IO;
|
||||
global using System.Linq;
|
||||
global using System.Net.Http;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">D:\DevCache\nuget-packages</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">D:\DevCache\nuget-packages;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages;C:\Program Files\dotnet\sdk\NuGetFallbackFolder</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="D:\DevCache\nuget-packages\" />
|
||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
||||
<SourceRoot Include="C:\Program Files\dotnet\sdk\NuGetFallbackFolder\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
|
||||
@@ -1,403 +0,0 @@
|
||||
{
|
||||
"version": 4,
|
||||
"targets": {
|
||||
"net10.0": {
|
||||
"QuantEngine.Application/1.0.0": {
|
||||
"type": "project",
|
||||
"framework": ".NETCoreApp,Version=v10.0",
|
||||
"dependencies": {
|
||||
"QuantEngine.Core": "1.0.0"
|
||||
},
|
||||
"compile": {
|
||||
"bin/placeholder/QuantEngine.Application.dll": {}
|
||||
},
|
||||
"runtime": {
|
||||
"bin/placeholder/QuantEngine.Application.dll": {}
|
||||
}
|
||||
},
|
||||
"QuantEngine.Core/1.0.0": {
|
||||
"type": "project",
|
||||
"framework": ".NETCoreApp,Version=v10.0",
|
||||
"compile": {
|
||||
"bin/placeholder/QuantEngine.Core.dll": {}
|
||||
},
|
||||
"runtime": {
|
||||
"bin/placeholder/QuantEngine.Core.dll": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"QuantEngine.Application/1.0.0": {
|
||||
"type": "project",
|
||||
"path": "../QuantEngine.Application/QuantEngine.Application.csproj",
|
||||
"msbuildProject": "../QuantEngine.Application/QuantEngine.Application.csproj"
|
||||
},
|
||||
"QuantEngine.Core/1.0.0": {
|
||||
"type": "project",
|
||||
"path": "../QuantEngine.Core/QuantEngine.Core.csproj",
|
||||
"msbuildProject": "../QuantEngine.Core/QuantEngine.Core.csproj"
|
||||
}
|
||||
},
|
||||
"projectFileDependencyGroups": {
|
||||
"net10.0": [
|
||||
"QuantEngine.Application >= 1.0.0",
|
||||
"QuantEngine.Core >= 1.0.0"
|
||||
]
|
||||
},
|
||||
"packageFolders": {
|
||||
"D:\\DevCache\\nuget-packages": {},
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {},
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder": {}
|
||||
},
|
||||
"project": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Tools\\QuantEngine.Tools.csproj",
|
||||
"projectName": "QuantEngine.Tools",
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Tools\\QuantEngine.Tools.csproj",
|
||||
"packagesPath": "D:\\DevCache\\nuget-packages",
|
||||
"outputPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Tools\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages",
|
||||
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\kjh20\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net10.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"C:\\Program Files\\dotnet\\library-packs": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj": {
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Application\\QuantEngine.Application.csproj"
|
||||
},
|
||||
"C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj": {
|
||||
"projectPath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Core\\QuantEngine.Core.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "all"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.300"
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"framework": "net10.0",
|
||||
"targetAlias": "net10.0",
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.301/PortableRuntimeIdentifierGraph.json",
|
||||
"packagesToPrune": {
|
||||
"Microsoft.CSharp": "(,4.7.32767]",
|
||||
"Microsoft.VisualBasic": "(,10.4.32767]",
|
||||
"Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"Microsoft.Win32.Registry": "(,5.0.32767]",
|
||||
"runtime.any.System.Collections": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.any.System.IO": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.aot.System.Collections": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.aot.System.IO": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Console": "(,4.3.32767]",
|
||||
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Console": "(,4.3.32767]",
|
||||
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"System.AppContext": "(,4.3.32767]",
|
||||
"System.Buffers": "(,5.0.32767]",
|
||||
"System.Collections": "(,4.3.32767]",
|
||||
"System.Collections.Concurrent": "(,4.3.32767]",
|
||||
"System.Collections.Immutable": "(,10.0.32767]",
|
||||
"System.Collections.NonGeneric": "(,4.3.32767]",
|
||||
"System.Collections.Specialized": "(,4.3.32767]",
|
||||
"System.ComponentModel": "(,4.3.32767]",
|
||||
"System.ComponentModel.Annotations": "(,4.3.32767]",
|
||||
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
|
||||
"System.ComponentModel.Primitives": "(,4.3.32767]",
|
||||
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
|
||||
"System.Console": "(,4.3.32767]",
|
||||
"System.Data.Common": "(,4.3.32767]",
|
||||
"System.Data.DataSetExtensions": "(,4.4.32767]",
|
||||
"System.Diagnostics.Contracts": "(,4.3.32767]",
|
||||
"System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"System.Diagnostics.DiagnosticSource": "(,10.0.32767]",
|
||||
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
|
||||
"System.Diagnostics.Process": "(,4.3.32767]",
|
||||
"System.Diagnostics.StackTrace": "(,4.3.32767]",
|
||||
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"System.Diagnostics.TraceSource": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"System.Drawing.Primitives": "(,4.3.32767]",
|
||||
"System.Dynamic.Runtime": "(,4.3.32767]",
|
||||
"System.Formats.Asn1": "(,10.0.32767]",
|
||||
"System.Formats.Tar": "(,10.0.32767]",
|
||||
"System.Globalization": "(,4.3.32767]",
|
||||
"System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"System.Globalization.Extensions": "(,4.3.32767]",
|
||||
"System.IO": "(,4.3.32767]",
|
||||
"System.IO.Compression": "(,4.3.32767]",
|
||||
"System.IO.Compression.ZipFile": "(,4.3.32767]",
|
||||
"System.IO.FileSystem": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
|
||||
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
|
||||
"System.IO.IsolatedStorage": "(,4.3.32767]",
|
||||
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
|
||||
"System.IO.Pipelines": "(,10.0.32767]",
|
||||
"System.IO.Pipes": "(,4.3.32767]",
|
||||
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
|
||||
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
|
||||
"System.Linq": "(,4.3.32767]",
|
||||
"System.Linq.AsyncEnumerable": "(,10.0.32767]",
|
||||
"System.Linq.Expressions": "(,4.3.32767]",
|
||||
"System.Linq.Parallel": "(,4.3.32767]",
|
||||
"System.Linq.Queryable": "(,4.3.32767]",
|
||||
"System.Memory": "(,5.0.32767]",
|
||||
"System.Net.Http": "(,4.3.32767]",
|
||||
"System.Net.Http.Json": "(,10.0.32767]",
|
||||
"System.Net.NameResolution": "(,4.3.32767]",
|
||||
"System.Net.NetworkInformation": "(,4.3.32767]",
|
||||
"System.Net.Ping": "(,4.3.32767]",
|
||||
"System.Net.Primitives": "(,4.3.32767]",
|
||||
"System.Net.Requests": "(,4.3.32767]",
|
||||
"System.Net.Security": "(,4.3.32767]",
|
||||
"System.Net.ServerSentEvents": "(,10.0.32767]",
|
||||
"System.Net.Sockets": "(,4.3.32767]",
|
||||
"System.Net.WebHeaderCollection": "(,4.3.32767]",
|
||||
"System.Net.WebSockets": "(,4.3.32767]",
|
||||
"System.Net.WebSockets.Client": "(,4.3.32767]",
|
||||
"System.Numerics.Vectors": "(,5.0.32767]",
|
||||
"System.ObjectModel": "(,4.3.32767]",
|
||||
"System.Private.DataContractSerialization": "(,4.3.32767]",
|
||||
"System.Private.Uri": "(,4.3.32767]",
|
||||
"System.Reflection": "(,4.3.32767]",
|
||||
"System.Reflection.DispatchProxy": "(,6.0.32767]",
|
||||
"System.Reflection.Emit": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
|
||||
"System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"System.Reflection.Metadata": "(,10.0.32767]",
|
||||
"System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"System.Reflection.TypeExtensions": "(,4.3.32767]",
|
||||
"System.Resources.Reader": "(,4.3.32767]",
|
||||
"System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"System.Resources.Writer": "(,4.3.32767]",
|
||||
"System.Runtime": "(,4.3.32767]",
|
||||
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
|
||||
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
|
||||
"System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"System.Runtime.Handles": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
|
||||
"System.Runtime.Loader": "(,4.3.32767]",
|
||||
"System.Runtime.Numerics": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Json": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
|
||||
"System.Security.AccessControl": "(,6.0.32767]",
|
||||
"System.Security.Claims": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Cng": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Csp": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
|
||||
"System.Security.Principal": "(,4.3.32767]",
|
||||
"System.Security.Principal.Windows": "(,5.0.32767]",
|
||||
"System.Security.SecureString": "(,4.3.32767]",
|
||||
"System.Text.Encoding": "(,4.3.32767]",
|
||||
"System.Text.Encoding.CodePages": "(,10.0.32767]",
|
||||
"System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"System.Text.Encodings.Web": "(,10.0.32767]",
|
||||
"System.Text.Json": "(,10.0.32767]",
|
||||
"System.Text.RegularExpressions": "(,4.3.32767]",
|
||||
"System.Threading": "(,4.3.32767]",
|
||||
"System.Threading.AccessControl": "(,10.0.32767]",
|
||||
"System.Threading.Channels": "(,10.0.32767]",
|
||||
"System.Threading.Overlapped": "(,4.3.32767]",
|
||||
"System.Threading.Tasks": "(,4.3.32767]",
|
||||
"System.Threading.Tasks.Dataflow": "(,10.0.32767]",
|
||||
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
|
||||
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
|
||||
"System.Threading.Thread": "(,4.3.32767]",
|
||||
"System.Threading.ThreadPool": "(,4.3.32767]",
|
||||
"System.Threading.Timer": "(,4.3.32767]",
|
||||
"System.ValueTuple": "(,4.5.32767]",
|
||||
"System.Xml.ReaderWriter": "(,4.3.32767]",
|
||||
"System.Xml.XDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlSerializer": "(,4.3.32767]",
|
||||
"System.Xml.XPath": "(,4.3.32767]",
|
||||
"System.Xml.XPath.XDocument": "(,5.0.32767]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "aiCDksw3TMY=",
|
||||
"success": true,
|
||||
"projectFilePath": "C:\\Temp\\data_feed\\src\\dotnet\\QuantEngine.Tools\\QuantEngine.Tools.csproj",
|
||||
"expectedPackageFiles": [],
|
||||
"logs": []
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using QuantEngine.Web.Client.Services;
|
||||
|
||||
namespace QuantEngine.Web.Client.Infrastructure
|
||||
{
|
||||
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
|
||||
{
|
||||
private readonly LocalStorageService _localStorage;
|
||||
private readonly HttpClient _http;
|
||||
private readonly ClaimsPrincipal _anonymous = new ClaimsPrincipal(new ClaimsIdentity());
|
||||
private const string TokenKey = "quant_admin_access_token";
|
||||
private const string UsernameKey = "quant_admin_username";
|
||||
private const string RoleKey = "quant_admin_role";
|
||||
private const string RememberUsernameKey = "quant_admin_remember_username";
|
||||
|
||||
public CustomAuthenticationStateProvider(LocalStorageService localStorage, HttpClient http)
|
||||
{
|
||||
_localStorage = localStorage;
|
||||
_http = http;
|
||||
}
|
||||
|
||||
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await _localStorage.GetAsync<string>(TokenKey);
|
||||
var username = await _localStorage.GetAsync<string>(UsernameKey);
|
||||
var role = await _localStorage.GetAsync<string>(RoleKey) ?? "Admin";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(token) && !string.IsNullOrWhiteSpace(username))
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "api/auth/me");
|
||||
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
||||
var response = await _http.SendAsync(request);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
await MarkUserAsLoggedOutAsync();
|
||||
return new AuthenticationState(_anonymous);
|
||||
}
|
||||
|
||||
var identity = new ClaimsIdentity(new[]
|
||||
{
|
||||
new Claim(ClaimTypes.Name, username),
|
||||
new Claim(ClaimTypes.Role, role)
|
||||
}, "QuantAdminAuth");
|
||||
|
||||
var user = new ClaimsPrincipal(identity);
|
||||
return new AuthenticationState(user);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Return anonymous if localStorage isn't ready
|
||||
}
|
||||
|
||||
return new AuthenticationState(_anonymous);
|
||||
}
|
||||
|
||||
public async Task MarkUserAsAuthenticatedAsync(string username, string accessToken, string role)
|
||||
{
|
||||
await MarkUserAsAuthenticatedAsync(username, accessToken, role, rememberUsername: true);
|
||||
}
|
||||
|
||||
public async Task MarkUserAsAuthenticatedAsync(string username, string accessToken, string role, bool rememberUsername)
|
||||
{
|
||||
await _localStorage.SetAsync(TokenKey, accessToken);
|
||||
if (rememberUsername)
|
||||
{
|
||||
await _localStorage.SetAsync(UsernameKey, username);
|
||||
await _localStorage.SetAsync(RememberUsernameKey, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _localStorage.DeleteAsync(UsernameKey);
|
||||
await _localStorage.SetAsync(RememberUsernameKey, false);
|
||||
}
|
||||
await _localStorage.SetAsync(RoleKey, role);
|
||||
|
||||
var identity = new ClaimsIdentity(new[]
|
||||
{
|
||||
new Claim(ClaimTypes.Name, username),
|
||||
new Claim(ClaimTypes.Role, role)
|
||||
}, "QuantAdminAuth");
|
||||
|
||||
var user = new ClaimsPrincipal(identity);
|
||||
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
|
||||
}
|
||||
|
||||
public async Task MarkUserAsLoggedOutAsync()
|
||||
{
|
||||
await _localStorage.DeleteAsync(TokenKey);
|
||||
await _localStorage.DeleteAsync(RoleKey);
|
||||
var rememberUsername = await _localStorage.GetAsync<bool>(RememberUsernameKey);
|
||||
if (!rememberUsername)
|
||||
{
|
||||
await _localStorage.DeleteAsync(UsernameKey);
|
||||
}
|
||||
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_anonymous)));
|
||||
}
|
||||
|
||||
public async Task LogoutFromServerAsync()
|
||||
{
|
||||
var token = await _localStorage.GetAsync<string>(TokenKey);
|
||||
if (!string.IsNullOrWhiteSpace(token))
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "api/auth/logout");
|
||||
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
||||
await _http.SendAsync(request);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Best-effort server revocation; always clear local state.
|
||||
}
|
||||
}
|
||||
|
||||
await MarkUserAsLoggedOutAsync();
|
||||
}
|
||||
|
||||
public async Task<string?> GetRememberedUsernameAsync()
|
||||
{
|
||||
var rememberUsername = await _localStorage.GetAsync<bool>(RememberUsernameKey);
|
||||
if (!rememberUsername)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return await _localStorage.GetAsync<string>(UsernameKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
@Body
|
||||
@@ -0,0 +1,69 @@
|
||||
@inherits LayoutComponentBase
|
||||
@inject HttpClient Http
|
||||
@inject AuthenticationStateProvider AuthStateProvider
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<MudLayout>
|
||||
<MudAppBar Elevation="1" Dense="true">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@(() => navOpen = !navOpen)" />
|
||||
<MudText Typo="Typo.h6">QuantEngine v@appVersion</MudText>
|
||||
<MudSpacer />
|
||||
<AuthorizeView>
|
||||
<Authorized>
|
||||
<MudText Typo="Typo.body2">관리자 (@context.User.Identity?.Name)</MudText>
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Error" OnClick="HandleLogoutAsync">로그아웃</MudButton>
|
||||
</Authorized>
|
||||
</AuthorizeView>
|
||||
</MudAppBar>
|
||||
|
||||
<MudDrawer Open="@navOpen" Variant="DrawerVariant.Responsive" Elevation="1">
|
||||
<MudNavMenu>
|
||||
<NavMenu />
|
||||
</MudNavMenu>
|
||||
<div style="padding: 16px; border-top: 1px solid var(--mud-palette-lines-default);">
|
||||
<MudText Typo="Typo.caption">QuantEngine v@appVersion</MudText>
|
||||
<MudText Typo="Typo.caption">배포: @buildTime</MudText>
|
||||
</div>
|
||||
</MudDrawer>
|
||||
|
||||
<MudMainContent>
|
||||
<MudContainer MaxWidth="MaxWidth.False" Class="pa-4">
|
||||
@Body
|
||||
</MudContainer>
|
||||
</MudMainContent>
|
||||
</MudLayout>
|
||||
|
||||
@code {
|
||||
private bool navOpen = true;
|
||||
private string appVersion = "Local Debug";
|
||||
private string buildTime = "N/A";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var versionInfo = await Http.GetFromJsonAsync<VersionInfo>("version.json");
|
||||
if (versionInfo != null)
|
||||
{
|
||||
appVersion = versionInfo.Version ?? "Local Debug";
|
||||
buildTime = versionInfo.Built ?? "N/A";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleLogoutAsync()
|
||||
{
|
||||
var customProvider = (CustomAuthenticationStateProvider)AuthStateProvider;
|
||||
await customProvider.LogoutFromServerAsync();
|
||||
NavigationManager.NavigateTo("/login");
|
||||
}
|
||||
|
||||
private class VersionInfo
|
||||
{
|
||||
public string? Version { get; set; }
|
||||
public string? Built { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<MudNavMenu>
|
||||
<MudNavLink Href="/dashboard" Match="NavLinkMatch.All">Dashboard</MudNavLink>
|
||||
<MudNavLink Href="/operations" Match="NavLinkMatch.Prefix">Operations</MudNavLink>
|
||||
</MudNavMenu>
|
||||
@@ -1,122 +1,93 @@
|
||||
@page "/collection"
|
||||
@using QuantEngine.Web.Services
|
||||
@attribute [Authorize]
|
||||
@using QuantEngine.Web.Client.Services
|
||||
@inject ApiClient ApiClient
|
||||
@inject ILogger<Collection> Logger
|
||||
|
||||
<PageTitle>QuantEngine - Collection</PageTitle>
|
||||
|
||||
<h1 style="margin: 0 0 8px 0; font-size: 28px; font-weight: 600;">Data Collection</h1>
|
||||
<p style="margin: 0 0 16px 0; color: var(--neutral-foreground-2); font-size: 14px;">
|
||||
KIS API data collection dashboard. Monitor runs, snapshots, and error trends.
|
||||
</p>
|
||||
<MudText Typo="Typo.h4" Class="mb-2">Data Collection</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mb-4">KIS API data collection dashboard. API-first로만 동작합니다.</MudText>
|
||||
|
||||
<!-- Controls -->
|
||||
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="8" Style="margin-bottom: 16px;">
|
||||
<FluentButton Appearance="ButtonAppearance.Primary" OnClick="@StartCollectionAsync" Disabled="@IsProcessing">
|
||||
@if (IsProcessing) { <span>Running...</span> } else { <span>Start Collection</span> }
|
||||
</FluentButton>
|
||||
<FluentButton Appearance="ButtonAppearance.Default" OnClick="@RefreshAsync" Disabled="@IsProcessing">
|
||||
Refresh
|
||||
</FluentButton>
|
||||
</FluentStack>
|
||||
<MudStack Row="true" Spacing="2" Class="mb-4">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@StartCollectionAsync" Disabled="@IsProcessing">
|
||||
@(IsProcessing ? "Running..." : "Start Collection")
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" OnClick="@RefreshAsync" Disabled="@IsProcessing">Refresh</MudButton>
|
||||
</MudStack>
|
||||
|
||||
<!-- Loading skeleton -->
|
||||
@if (IsLoading)
|
||||
{
|
||||
<FluentStack Orientation="Orientation.Vertical" VerticalGap="16">
|
||||
<FluentSkeleton Width="100%" Height="60px" />
|
||||
<FluentSkeleton Width="100%" Height="200px" />
|
||||
</FluentStack>
|
||||
<MudProgressLinear Indeterminate="true" Color="Color.Primary" Class="mb-4" />
|
||||
}
|
||||
else if (DashboardState != null)
|
||||
{
|
||||
<!-- Summary Cards -->
|
||||
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="16" Wrap="true" Style="margin-bottom: 16px;">
|
||||
<FluentCard Style="flex: 1; min-width: 150px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Last Run</p>
|
||||
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@(DashboardState.LastRunStatus ?? "N/A")</h3>
|
||||
<p style="margin: 8px 0 0 0; color: var(--neutral-foreground-3); font-size: 12px;">@(DashboardState.LastFinishedAt ?? "Not finished")</p>
|
||||
</div>
|
||||
</FluentCard>
|
||||
<FluentCard Style="flex: 1; min-width: 150px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Total Snapshots</p>
|
||||
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@DashboardState.TotalSnapshots</h3>
|
||||
</div>
|
||||
</FluentCard>
|
||||
<FluentCard Style="flex: 1; min-width: 150px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Total Errors</p>
|
||||
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@DashboardState.TotalErrors</h3>
|
||||
</div>
|
||||
</FluentCard>
|
||||
</FluentStack>
|
||||
<MudGrid Spacing="2" Class="mb-4">
|
||||
<MudItem xs="12" sm="4">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">Last Run</MudText>
|
||||
<MudText Typo="Typo.h6">@(DashboardState.LastRunStatus ?? "N/A")</MudText>
|
||||
<MudText Typo="Typo.body2">@(DashboardState.LastFinishedAt ?? "Not finished")</MudText>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="4">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">Total Snapshots</MudText>
|
||||
<MudText Typo="Typo.h6">@DashboardState.TotalSnapshots</MudText>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="4">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">Total Errors</MudText>
|
||||
<MudText Typo="Typo.h6">@DashboardState.TotalErrors</MudText>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
||||
<!-- Recent Errors -->
|
||||
@if (DashboardState.RecentErrors.Count > 0)
|
||||
{
|
||||
<FluentCard Style="margin-bottom: 16px;">
|
||||
<div style="padding: 16px;">
|
||||
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Recent Errors</h3>
|
||||
<table style="width: 100%; border-collapse: collapse;">
|
||||
<thead style="background: var(--neutral-subtle);">
|
||||
<tr>
|
||||
<th style="padding: 8px; text-align: left; border-bottom: 1px solid var(--neutral-divider-rest);">Source</th>
|
||||
<th style="padding: 8px; text-align: left; border-bottom: 1px solid var(--neutral-divider-rest);">Kind</th>
|
||||
<th style="padding: 8px; text-align: left; border-bottom: 1px solid var(--neutral-divider-rest);">Ticker</th>
|
||||
<th style="padding: 8px; text-align: left; border-bottom: 1px solid var(--neutral-divider-rest);">Message</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var error in DashboardState.RecentErrors)
|
||||
{
|
||||
<tr>
|
||||
<td style="padding: 8px; border-bottom: 1px solid var(--neutral-stroke-divider-rest);">@error.SourceName</td>
|
||||
<td style="padding: 8px; border-bottom: 1px solid var(--neutral-stroke-divider-rest);">@error.ErrorKind</td>
|
||||
<td style="padding: 8px; border-bottom: 1px solid var(--neutral-stroke-divider-rest);">@error.Ticker</td>
|
||||
<td style="padding: 8px; border-bottom: 1px solid var(--neutral-stroke-divider-rest);">@error.ErrorMessage</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</FluentCard>
|
||||
<MudPaper Class="pa-4 mb-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Recent Errors</MudText>
|
||||
<MudTable Items="@DashboardState.RecentErrors" Dense="true" Hover="true">
|
||||
<HeaderContent>
|
||||
<MudTh>Source</MudTh>
|
||||
<MudTh>Kind</MudTh>
|
||||
<MudTh>Ticker</MudTh>
|
||||
<MudTh>Message</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Source">@context.SourceName</MudTd>
|
||||
<MudTd DataLabel="Kind">@context.ErrorKind</MudTd>
|
||||
<MudTd DataLabel="Ticker">@context.Ticker</MudTd>
|
||||
<MudTd DataLabel="Message">@context.ErrorMessage</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
</MudPaper>
|
||||
}
|
||||
|
||||
<!-- Recent Runs -->
|
||||
@if (RecentRuns != null && RecentRuns.Count > 0)
|
||||
{
|
||||
<FluentCard>
|
||||
<div style="padding: 16px;">
|
||||
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Recent Runs</h3>
|
||||
<table style="width: 100%; border-collapse: collapse;">
|
||||
<thead style="background: var(--neutral-subtle);">
|
||||
<tr>
|
||||
<th style="padding: 8px; text-align: left; border-bottom: 1px solid var(--neutral-divider-rest);">Run ID</th>
|
||||
<th style="padding: 8px; text-align: left; border-bottom: 1px solid var(--neutral-divider-rest);">Status</th>
|
||||
<th style="padding: 8px; text-align: left; border-bottom: 1px solid var(--neutral-divider-rest);">Started</th>
|
||||
<th style="padding: 8px; text-align: left; border-bottom: 1px solid var(--neutral-divider-rest);">Finished</th>
|
||||
<th style="padding: 8px; text-align: left; border-bottom: 1px solid var(--neutral-divider-rest);">Snapshots</th>
|
||||
<th style="padding: 8px; text-align: left; border-bottom: 1px solid var(--neutral-divider-rest);">Errors</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var run in RecentRuns)
|
||||
{
|
||||
<tr>
|
||||
<td style="padding: 8px; border-bottom: 1px solid var(--neutral-stroke-divider-rest); font-family: monospace; font-size: 12px;">@run.RunId</td>
|
||||
<td style="padding: 8px; border-bottom: 1px solid var(--neutral-stroke-divider-rest);">@run.Status</td>
|
||||
<td style="padding: 8px; border-bottom: 1px solid var(--neutral-stroke-divider-rest); font-size: 12px;">@run.StartedAt</td>
|
||||
<td style="padding: 8px; border-bottom: 1px solid var(--neutral-stroke-divider-rest); font-size: 12px;">@run.FinishedAt</td>
|
||||
<td style="padding: 8px; border-bottom: 1px solid var(--neutral-stroke-divider-rest);">@run.TotalSnapshots</td>
|
||||
<td style="padding: 8px; border-bottom: 1px solid var(--neutral-stroke-divider-rest);">@run.TotalErrors</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</FluentCard>
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Recent Runs</MudText>
|
||||
<MudTable Items="@RecentRuns" Dense="true" Hover="true">
|
||||
<HeaderContent>
|
||||
<MudTh>Run ID</MudTh>
|
||||
<MudTh>Status</MudTh>
|
||||
<MudTh>Started</MudTh>
|
||||
<MudTh>Finished</MudTh>
|
||||
<MudTh>Snapshots</MudTh>
|
||||
<MudTh>Errors</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Run ID" Style="font-family: monospace; font-size: 12px;">@context.RunId</MudTd>
|
||||
<MudTd DataLabel="Status">@context.Status</MudTd>
|
||||
<MudTd DataLabel="Started">@context.StartedAt</MudTd>
|
||||
<MudTd DataLabel="Finished">@context.FinishedAt</MudTd>
|
||||
<MudTd DataLabel="Snapshots">@context.TotalSnapshots</MudTd>
|
||||
<MudTd DataLabel="Errors">@context.TotalErrors</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
</MudPaper>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +108,6 @@ else if (DashboardState != null)
|
||||
try
|
||||
{
|
||||
DashboardState = await ApiClient.GetCollectionStateAsync();
|
||||
|
||||
var runsResponse = await ApiClient.GetCollectionRunsAsync(10);
|
||||
RecentRuns = runsResponse?.Runs ?? new();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
@page "/dashboard"
|
||||
@attribute [Authorize]
|
||||
@using QuantEngine.Core.Infrastructure
|
||||
@inject HttpClient Http
|
||||
|
||||
<PageTitle>Quant Engine - Dashboard</PageTitle>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mb-2">Quant Engine</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mb-4">운영 진입점입니다. 로그인 후 현재 스냅샷 상태와 리포트 경로만 표시합니다.</MudText>
|
||||
|
||||
<MudGrid Spacing="2" Class="mb-4">
|
||||
<MudItem xs="12" sm="4">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">Operational Report</MudText>
|
||||
<MudText Typo="Typo.h6">@ReportStateLabel</MudText>
|
||||
<MudText Typo="Typo.body2">@ReportPath</MudText>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="4">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">Sections</MudText>
|
||||
<MudText Typo="Typo.h6">@SectionCountLabel</MudText>
|
||||
<MudText Typo="Typo.body2">Temp/operational_report.json</MudText>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="4">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">Primary Route</MudText>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Href="/operations" Class="mt-2">Open Operations</MudButton>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
||||
<MudGrid Spacing="2" Class="mb-4">
|
||||
<MudItem xs="12" md="8">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Current State</MudText>
|
||||
<MudStack Spacing="1">
|
||||
<MudText Typo="Typo.body2">Status: <MudChip T="string" Color="@(ReportChipLabel == "READY" ? Color.Success : Color.Warning)" Variant="Variant.Filled">@ReportChipLabel</MudChip></MudText>
|
||||
<MudText Typo="Typo.body2">Generated: @GeneratedAtLabel</MudText>
|
||||
<MudText Typo="Typo.body2">Source: @SourceLabel</MudText>
|
||||
<MudText Typo="Typo.body2">Decision feed: @DecisionFeedLabel</MudText>
|
||||
<MudText Typo="Typo.body2">Factor feed: @FactorFeedLabel</MudText>
|
||||
<MudText Typo="Typo.body2">Raw feed: @RawFeedLabel</MudText>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
<MudItem xs="12" md="4">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Routing Notes</MudText>
|
||||
<ul style="margin: 0; padding-left: 18px;">
|
||||
<li>운영 데이터는 snapshot 우선입니다.</li>
|
||||
<li>Excel/GAS 의존 문구는 제거 대상입니다.</li>
|
||||
<li>숫자는 provenance 없으면 표시하지 않습니다.</li>
|
||||
</ul>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Coverage Summary</MudText>
|
||||
@if (Sections.Count == 0)
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning">DATA_MISSING: operational_report.json이 비어 있거나 아직 생성되지 않았습니다.</MudAlert>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTable Items="@Sections" Dense="true" Hover="true">
|
||||
<HeaderContent>
|
||||
<MudTh>Name</MudTh>
|
||||
<MudTh>Title</MudTh>
|
||||
<MudTh>Preview</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Name">@context.Name</MudTd>
|
||||
<MudTd DataLabel="Title">@context.Title</MudTd>
|
||||
<MudTd DataLabel="Preview">@context.Preview</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
private readonly List<OperationalReportSection> Sections = new();
|
||||
private string ReportStateLabel = "DATA_MISSING";
|
||||
private string ReportChipLabel = "DATA_MISSING";
|
||||
private string SectionCountLabel = "0";
|
||||
private string GeneratedAtLabel = "n/a";
|
||||
private string SourceLabel = "n/a";
|
||||
private string DecisionFeedLabel = "DISCONNECTED";
|
||||
private string FactorFeedLabel = "DISCONNECTED";
|
||||
private string RawFeedLabel = "DISCONNECTED";
|
||||
private string ReportPath = "n/a";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var report = await Http.GetFromJsonAsync<OperationalReportData>("api/operational-report");
|
||||
if (report != null)
|
||||
{
|
||||
Sections.Clear();
|
||||
Sections.AddRange(report.Sections);
|
||||
SectionCountLabel = report.SectionCount.ToString();
|
||||
GeneratedAtLabel = report.GeneratedAt;
|
||||
SourceLabel = report.SourceJson;
|
||||
ReportStateLabel = Sections.Count > 0 ? "READY" : "DATA_MISSING";
|
||||
ReportChipLabel = Sections.Count > 0 ? "READY" : "DATA_MISSING";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
ReportStateLabel = "DATA_MISSING";
|
||||
ReportChipLabel = "DATA_MISSING";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
@page "/login"
|
||||
@attribute [AllowAnonymous]
|
||||
@layout AuthLayout
|
||||
@inject AuthenticationStateProvider AuthStateProvider
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject HttpClient Http
|
||||
|
||||
<PageTitle>로그인 - QuantEngine</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.False" Class="login-shell">
|
||||
<MudPaper Class="login-card pa-8" Elevation="10">
|
||||
<MudStack AlignItems="AlignItems.Center" Spacing="2" Class="mb-6">
|
||||
<MudAvatar Size="Size.Large" Color="Color.Primary">Q</MudAvatar>
|
||||
<MudText Typo="Typo.h4">QuantEngine</MudText>
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">은퇴자산포트폴리오 투자 관리 시스템</MudText>
|
||||
</MudStack>
|
||||
|
||||
<MudStack Spacing="2">
|
||||
<MudTextField Label="관리자 아이디" @bind-Value="Username" Variant="Variant.Outlined" Immediate="true" AutoFocus="true" />
|
||||
<MudTextField Label="비밀번호" @bind-Value="Password" Variant="Variant.Outlined" InputType="InputType.Password" Immediate="true" />
|
||||
<MudCheckBox T="bool" @bind-Checked="RememberUsername" Color="Color.Primary" Label="아이디 저장" />
|
||||
|
||||
@if (!string.IsNullOrEmpty(ErrorMessage))
|
||||
{
|
||||
<MudAlert Severity="Severity.Error">@ErrorMessage</MudAlert>
|
||||
}
|
||||
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" FullWidth="true" Disabled="@IsSubmitting" OnClick="HandleLoginAsync">
|
||||
@(IsSubmitting ? "인증 중..." : "로그인")
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
</MudContainer>
|
||||
|
||||
<style>
|
||||
.login-shell {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background:
|
||||
radial-gradient(circle at top left, rgba(0, 242, 254, 0.08), transparent 30%),
|
||||
radial-gradient(circle at bottom right, rgba(79, 172, 254, 0.1), transparent 35%),
|
||||
linear-gradient(135deg, #090a15 0%, #12142d 100%);
|
||||
}
|
||||
|
||||
.login-card {
|
||||
width: min(480px, calc(100vw - 32px));
|
||||
border-radius: 20px;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
backdrop-filter: blur(24px);
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
@code {
|
||||
private string Username { get; set; } = string.Empty;
|
||||
private string Password { get; set; } = string.Empty;
|
||||
private string ErrorMessage { get; set; } = string.Empty;
|
||||
private bool IsSubmitting { get; set; } = false;
|
||||
private bool RememberUsername { get; set; } = true;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var customProvider = (CustomAuthenticationStateProvider)AuthStateProvider;
|
||||
var remembered = await customProvider.GetRememberedUsernameAsync();
|
||||
if (!string.IsNullOrWhiteSpace(remembered))
|
||||
{
|
||||
Username = remembered;
|
||||
RememberUsername = true;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class LoginResponse
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string? Username { get; set; }
|
||||
public string? Role { get; set; }
|
||||
public string? AccessToken { get; set; }
|
||||
public string? ExpiresAt { get; set; }
|
||||
}
|
||||
|
||||
private async Task HandleLoginAsync()
|
||||
{
|
||||
ErrorMessage = string.Empty;
|
||||
if (string.IsNullOrWhiteSpace(Username) || string.IsNullOrWhiteSpace(Password))
|
||||
{
|
||||
ErrorMessage = "아이디와 비밀번호를 모두 입력해 주세요.";
|
||||
return;
|
||||
}
|
||||
|
||||
IsSubmitting = true;
|
||||
|
||||
try
|
||||
{
|
||||
var response = await Http.PostAsJsonAsync("api/auth/login", new { Username, Password });
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var auth = await response.Content.ReadFromJsonAsync<LoginResponse>();
|
||||
if (auth is null || string.IsNullOrWhiteSpace(auth.AccessToken))
|
||||
{
|
||||
ErrorMessage = "로그인 응답이 유효하지 않습니다.";
|
||||
return;
|
||||
}
|
||||
|
||||
var customProvider = (CustomAuthenticationStateProvider)AuthStateProvider;
|
||||
await customProvider.MarkUserAsAuthenticatedAsync(auth.Username ?? Username, auth.AccessToken, auth.Role ?? "Admin", RememberUsername);
|
||||
NavigationManager.NavigateTo("/dashboard");
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorMessage = "아이디 또는 비밀번호가 올바르지 않습니다.";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorMessage = $"로그인 중 오류가 발생했습니다: {ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsSubmitting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
@page "/operations"
|
||||
@attribute [Authorize]
|
||||
@using QuantEngine.Core.Infrastructure
|
||||
@inject HttpClient Http
|
||||
|
||||
<PageTitle>QuantEngine - Operations</PageTitle>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mb-2">Operational Report</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mb-4">Temp/operational_report.json만 읽는 운영 고정 화면입니다.</MudText>
|
||||
|
||||
<MudGrid Spacing="2" Class="mb-4">
|
||||
<MudItem xs="12" sm="3">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">Schema</MudText>
|
||||
<MudText Typo="Typo.h6">@SchemaVersion</MudText>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="3">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">Sections</MudText>
|
||||
<MudText Typo="Typo.h6">@SectionCountLabel</MudText>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="3">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">Source</MudText>
|
||||
<MudText Typo="Typo.h6">@SourceJson</MudText>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="3">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">Generated</MudText>
|
||||
<MudText Typo="Typo.h6">@GeneratedAt</MudText>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
||||
<MudGrid Spacing="2" Class="mb-4">
|
||||
@foreach (var section in HighlightSections)
|
||||
{
|
||||
<MudItem xs="12" sm="6" md="3" @key="section.Name">
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.caption">@(section.Name)</MudText>
|
||||
<MudText Typo="Typo.h6">@(section.Title)</MudText>
|
||||
<MudText Typo="Typo.body2">@(section.Preview)</MudText>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
}
|
||||
</MudGrid>
|
||||
|
||||
<MudPaper Class="pa-4 mb-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Report Health</MudText>
|
||||
<MudStack Spacing="1">
|
||||
<MudText Typo="Typo.body2">Status: <MudChip T="string" Color="@(HealthLabel == "PASS" ? Color.Success : Color.Warning)" Variant="Variant.Filled">@HealthLabel</MudChip></MudText>
|
||||
<MudText Typo="Typo.body2">Path: @ReportPath</MudText>
|
||||
<MudText Typo="Typo.body2">Sections rendered: @RenderedSectionCountLabel</MudText>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Sections</MudText>
|
||||
@if (Sections.Count == 0)
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning">DATA_MISSING: operational_report.json에 표시할 섹션이 없습니다.</MudAlert>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTable Items="@Sections" Dense="true" Hover="true">
|
||||
<HeaderContent>
|
||||
<MudTh>Name</MudTh>
|
||||
<MudTh>Title</MudTh>
|
||||
<MudTh>Preview</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Name">@context.Name</MudTd>
|
||||
<MudTd DataLabel="Title">@context.Title</MudTd>
|
||||
<MudTd DataLabel="Preview">@context.Preview</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
private readonly List<OperationalReportSection> Sections = new();
|
||||
private readonly List<OperationalReportSection> HighlightSections = new();
|
||||
private string SchemaVersion = "n/a";
|
||||
private string SourceJson = "n/a";
|
||||
private string GeneratedAt = "n/a";
|
||||
private string SectionCountLabel = "0";
|
||||
private string RenderedSectionCountLabel = "0";
|
||||
private string HealthLabel = "DATA_MISSING";
|
||||
private string ReportPath = "n/a";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var report = await Http.GetFromJsonAsync<OperationalReportData>("api/operational-report");
|
||||
if (report != null)
|
||||
{
|
||||
SchemaVersion = report.SchemaVersion;
|
||||
SourceJson = report.SourceJson;
|
||||
GeneratedAt = report.GeneratedAt;
|
||||
|
||||
Sections.Clear();
|
||||
Sections.AddRange(report.Sections);
|
||||
|
||||
HighlightSections.Clear();
|
||||
HighlightSections.AddRange(Sections.Take(4));
|
||||
|
||||
SectionCountLabel = report.SectionCount.ToString();
|
||||
RenderedSectionCountLabel = Sections.Count.ToString();
|
||||
HealthLabel = Sections.Count > 0 ? "PASS" : "DATA_MISSING";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
HealthLabel = "DATA_MISSING";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using QuantEngine.Web.Client.Services;
|
||||
using QuantEngine.Web.Client.Infrastructure;
|
||||
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||
|
||||
// Register LocalStorage for cross-platform session persistence
|
||||
builder.Services.AddScoped<LocalStorageService>();
|
||||
|
||||
// Authentication setup in WebAssembly client
|
||||
builder.Services.AddAuthorizationCore();
|
||||
builder.Services.AddCascadingAuthenticationState();
|
||||
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
|
||||
|
||||
// HttpClient register (API-First standard)
|
||||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
||||
|
||||
await builder.Build().RunAsync();
|
||||
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
|
||||
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\QuantEngine.Core\QuantEngine.Core.csproj" />
|
||||
<ProjectReference Include="..\..\QuantEngine.Application\QuantEngine.Application.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.0-preview.2.25120.18" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.0-preview.2.25120.18" />
|
||||
<PackageReference Include="MudBlazor" Version="8.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,8 @@
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@code {
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
NavigationManager.NavigateTo("login");
|
||||
}
|
||||
}
|
||||
+6
-9
@@ -2,19 +2,16 @@ using System.Net.Http.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using QuantEngine.Core.Interfaces;
|
||||
|
||||
namespace QuantEngine.Web.Services;
|
||||
namespace QuantEngine.Web.Client.Services;
|
||||
|
||||
public class ApiClient
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly ILogger<ApiClient> _logger;
|
||||
private string BaseUrl { get; set; }
|
||||
|
||||
public ApiClient(HttpClient http, ILogger<ApiClient> logger)
|
||||
{
|
||||
_http = http;
|
||||
_logger = logger;
|
||||
BaseUrl = "http://localhost:5001"; // Default for Blazor Server
|
||||
}
|
||||
|
||||
// Collection API Methods
|
||||
@@ -23,7 +20,7 @@ public class ApiClient
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _http.GetFromJsonAsync<CollectionDashboardStateDto>($"{BaseUrl}/api/collection/state");
|
||||
return await _http.GetFromJsonAsync<CollectionDashboardStateDto>("api/collection/state");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -36,7 +33,7 @@ public class ApiClient
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _http.GetFromJsonAsync<CollectionRunsResponse>($"{BaseUrl}/api/collection/runs?limit={limit}");
|
||||
return await _http.GetFromJsonAsync<CollectionRunsResponse>($"api/collection/runs?limit={limit}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -49,7 +46,7 @@ public class ApiClient
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _http.GetFromJsonAsync<CollectionRunSnapshotsResponse>($"{BaseUrl}/api/collection/runs/{runId}/snapshots");
|
||||
return await _http.GetFromJsonAsync<CollectionRunSnapshotsResponse>($"api/collection/runs/{runId}/snapshots");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -62,7 +59,7 @@ public class ApiClient
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _http.GetFromJsonAsync<CollectionRunErrorsResponse>($"{BaseUrl}/api/collection/runs/{runId}/errors?limit={limit}");
|
||||
return await _http.GetFromJsonAsync<CollectionRunErrorsResponse>($"api/collection/runs/{runId}/errors?limit={limit}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -75,7 +72,7 @@ public class ApiClient
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _http.PostAsJsonAsync($"{BaseUrl}/api/collection/run", new { });
|
||||
var response = await _http.PostAsJsonAsync("api/collection/run", new { });
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return await response.Content.ReadFromJsonAsync<CollectionRunStartResponse>();
|
||||
@@ -0,0 +1,43 @@
|
||||
using Microsoft.JSInterop;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace QuantEngine.Web.Client.Services
|
||||
{
|
||||
public class LocalStorageService
|
||||
{
|
||||
private readonly IJSRuntime _js;
|
||||
|
||||
public LocalStorageService(IJSRuntime js)
|
||||
{
|
||||
_js = js;
|
||||
}
|
||||
|
||||
public async Task SetAsync<T>(string key, T value)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(value);
|
||||
await _js.InvokeVoidAsync("localStorage.setItem", key, json);
|
||||
}
|
||||
|
||||
public async Task<T?> GetAsync<T>(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
var json = await _js.InvokeAsync<string?>("localStorage.getItem", key);
|
||||
if (string.IsNullOrEmpty(json))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
return JsonSerializer.Deserialize<T>(json);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(string key)
|
||||
{
|
||||
await _js.InvokeVoidAsync("localStorage.removeItem", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,11 @@
|
||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using Microsoft.FluentUI.AspNetCore.Components
|
||||
@using Microsoft.FluentUI.AspNetCore.Components.Icons
|
||||
@using QuantEngine.Web
|
||||
@using QuantEngine.Web.Components
|
||||
@using QuantEngine.Web.Components.Layout
|
||||
@using QuantEngine.Web.Services
|
||||
@using MudBlazor
|
||||
@using QuantEngine.Web.Client
|
||||
@using QuantEngine.Web.Client.Pages
|
||||
@using QuantEngine.Web.Client.Layout
|
||||
@using QuantEngine.Web.Client.Infrastructure
|
||||
@using QuantEngine.Web.Client.Services
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="ko">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<base href="/quant/" />
|
||||
<base href="/" />
|
||||
<ResourcePreloader />
|
||||
<!-- Fluent UI CSS -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
|
||||
<link href="_content/Microsoft.FluentUI.AspNetCore.Components/css/fluent-components.css" rel="stylesheet" />
|
||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="@Assets["app.css"]" />
|
||||
<link rel="stylesheet" href="@Assets["QuantEngine.Web.styles.css"]" />
|
||||
<ImportMap />
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<HeadOutlet />
|
||||
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
|
||||
<link rel="alternate icon" type="image/png" href="favicon.png" />
|
||||
<HeadOutlet @rendermode="InteractiveWebAssembly" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<FluentDesignSystemProvider>
|
||||
<Routes />
|
||||
<ReconnectModal />
|
||||
</FluentDesignSystemProvider>
|
||||
<MudThemeProvider />
|
||||
<MudDialogProvider />
|
||||
<MudSnackbarProvider />
|
||||
<Routes @rendermode="InteractiveWebAssembly" />
|
||||
<ReconnectModal />
|
||||
|
||||
<!-- Fluent UI JS -->
|
||||
<script src="_content/Microsoft.FluentUI.AspNetCore.Components/js/fluent-components.js"></script>
|
||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
||||
<script src="@Assets["_framework/blazor.web.js"]"></script>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
@inherits LayoutComponentBase
|
||||
@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment WebHostEnvironment
|
||||
@using System.IO
|
||||
@using System.Text.Json
|
||||
@using Microsoft.FluentUI.AspNetCore.Components
|
||||
|
||||
<FluentStack Orientation="Orientation.Vertical" Class="h-100 w-100">
|
||||
<!-- Header -->
|
||||
<FluentHeader>
|
||||
<FluentStack Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"
|
||||
Style="width: 100%; padding: 8px 16px; gap: 16px;">
|
||||
<FluentButton OnClick="@(() => navOpen = !navOpen)"
|
||||
Title="Toggle Navigation"
|
||||
Style="background: transparent; border: none; cursor: pointer;">
|
||||
☰
|
||||
</FluentButton>
|
||||
<h1 style="margin: 0; font-size: 20px; font-weight: 600;">QuantEngine v@appVersion</h1>
|
||||
</FluentStack>
|
||||
</FluentHeader>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<FluentStack Orientation="Orientation.Horizontal" Class="flex-1" Style="overflow: hidden;">
|
||||
<!-- Navigation Sidebar -->
|
||||
@if (navOpen)
|
||||
{
|
||||
<nav style="width: 240px; background: var(--neutral-layer-1); border-right: 1px solid var(--neutral-stroke-1); padding: 12px; overflow-y: auto;">
|
||||
<NavMenu />
|
||||
<div style="margin-top: auto; padding-top: 12px; border-top: 1px solid var(--neutral-stroke-1); margin-top: 12px; font-size: 11px; color: var(--neutral-foreground-3); line-height: 1.5;">
|
||||
<div style="font-weight: 500; margin-bottom: 2px;">QuantEngine v@appVersion</div>
|
||||
<div style="font-size: 10px; opacity: 0.85;">배포: @buildTime</div>
|
||||
</div>
|
||||
</nav>
|
||||
}
|
||||
|
||||
<!-- Page Content -->
|
||||
<FluentStack Orientation="Orientation.Vertical" Class="flex-1" Style="overflow-y: auto; padding: 24px;">
|
||||
@Body
|
||||
</FluentStack>
|
||||
</FluentStack>
|
||||
</FluentStack>
|
||||
|
||||
<div id="blazor-error-ui" data-nosnippet>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p>An unhandled error has occurred.</p>
|
||||
<a href="." class="btn btn-primary">Reload</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.h-100 {
|
||||
height: 100%;
|
||||
}
|
||||
.w-100 {
|
||||
width: 100%;
|
||||
}
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
||||
@code {
|
||||
private bool navOpen = true;
|
||||
private string appVersion = "Local Debug";
|
||||
private string buildTime = "N/A";
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
try
|
||||
{
|
||||
var versionFilePath = Path.Combine(WebHostEnvironment.WebRootPath, "version.json");
|
||||
if (File.Exists(versionFilePath))
|
||||
{
|
||||
var jsonContent = File.ReadAllText(versionFilePath);
|
||||
using var doc = System.Text.Json.JsonDocument.Parse(jsonContent);
|
||||
var root = doc.RootElement;
|
||||
|
||||
if (root.TryGetProperty("version", out var versionProp))
|
||||
{
|
||||
appVersion = versionProp.GetString() ?? "Local Debug";
|
||||
}
|
||||
if (root.TryGetProperty("built", out var builtProp))
|
||||
{
|
||||
buildTime = builtProp.GetString() ?? "N/A";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Fail-safe default fallback values
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
@using Microsoft.FluentUI.AspNetCore.Components
|
||||
|
||||
<FluentNavMenu>
|
||||
<FluentNavLink Href="/" Match="NavLinkMatch.All">
|
||||
Dashboard
|
||||
</FluentNavLink>
|
||||
<FluentNavLink Href="/operations" Match="NavLinkMatch.Prefix">
|
||||
Operations
|
||||
</FluentNavLink>
|
||||
</FluentNavMenu>
|
||||
@@ -1,110 +0,0 @@
|
||||
@page "/"
|
||||
@using QuantEngine.Core.Infrastructure
|
||||
@inject IWebHostEnvironment Environment
|
||||
|
||||
<PageTitle>Quant Engine - Dashboard</PageTitle>
|
||||
|
||||
<h1 style="margin: 0 0 8px 0; font-size: 28px; font-weight: 600;">Quant Engine</h1>
|
||||
<p style="margin: 0 0 16px 0; color: var(--neutral-foreground-2); font-size: 14px;">
|
||||
루트 화면은 운영 진입점입니다. 가짜 성과 수치 없이 현재 스냅샷 상태와 리포트 경로만 보여줍니다.
|
||||
</p>
|
||||
|
||||
<!-- Top 3 Cards -->
|
||||
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="16" Wrap="true" Style="margin-bottom: 16px;">
|
||||
<FluentCard Style="flex: 1; min-width: 200px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Operational Report</p>
|
||||
<h3 style="margin: 0; font-size: 20px; font-weight: 600;">@ReportStateLabel</h3>
|
||||
<p style="margin: 8px 0 0 0; color: var(--neutral-foreground-3); font-size: 12px;">@ReportPath</p>
|
||||
</div>
|
||||
</FluentCard>
|
||||
<FluentCard Style="flex: 1; min-width: 200px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Sections</p>
|
||||
<h3 style="margin: 0; font-size: 20px; font-weight: 600;">@SectionCountLabel</h3>
|
||||
<p style="margin: 8px 0 0 0; color: var(--neutral-foreground-3); font-size: 12px;">Temp/operational_report.json</p>
|
||||
</div>
|
||||
</FluentCard>
|
||||
<FluentCard Style="flex: 1; min-width: 200px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Primary Route</p>
|
||||
<FluentButton Appearance="ButtonAppearance.Primary" Href="/operations" Style="margin-top: 8px;">
|
||||
Open Operations
|
||||
</FluentButton>
|
||||
</div>
|
||||
</FluentCard>
|
||||
</FluentStack>
|
||||
|
||||
<!-- Current State & Routing Notes -->
|
||||
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="16" Wrap="true" Style="margin-bottom: 16px;">
|
||||
<FluentCard Style="flex: 2; min-width: 300px;">
|
||||
<div style="padding: 16px;">
|
||||
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Current State</h3>
|
||||
<FluentStack Orientation="Orientation.Vertical" VerticalGap="8">
|
||||
<p style="margin: 0; font-size: 14px;"><strong>Status:</strong> <FluentBadge Appearance="BadgeAppearance.Filled">@ReportChipLabel</FluentBadge></p>
|
||||
<p style="margin: 0; font-size: 14px;"><strong>Generated:</strong> @GeneratedAtLabel</p>
|
||||
<p style="margin: 0; font-size: 14px;"><strong>Source:</strong> @SourceLabel</p>
|
||||
<p style="margin: 0; font-size: 14px;"><strong>Decision feed:</strong> @DecisionFeedLabel</p>
|
||||
<p style="margin: 0; font-size: 14px;"><strong>Factor feed:</strong> @FactorFeedLabel</p>
|
||||
<p style="margin: 0; font-size: 14px;"><strong>Raw feed:</strong> @RawFeedLabel</p>
|
||||
</FluentStack>
|
||||
</div>
|
||||
</FluentCard>
|
||||
|
||||
<FluentCard Style="flex: 1; min-width: 250px;">
|
||||
<div style="padding: 16px;">
|
||||
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Routing Notes</h3>
|
||||
<ul style="margin: 0; padding-left: 16px; font-size: 14px;">
|
||||
<li>운영 데이터는 snapshot 우선입니다.</li>
|
||||
<li>Excel/GAS 의존 문구는 운영 경로에서 제거 대상입니다.</li>
|
||||
<li>숫자는 provenance 없으면 표시하지 않습니다.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</FluentCard>
|
||||
</FluentStack>
|
||||
|
||||
<!-- Coverage Summary -->
|
||||
<FluentCard>
|
||||
<div style="padding: 16px;">
|
||||
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Coverage Summary</h3>
|
||||
@if (Sections.Count == 0)
|
||||
{
|
||||
<div style="padding: 12px; background: var(--warning-background-1); border: 1px solid var(--warning-stroke-1); border-radius: 4px; color: var(--warning-foreground-1); font-size: 14px;">
|
||||
DATA_MISSING: operational_report.json이 비어 있거나 아직 생성되지 않았습니다.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<FluentDataGrid Items="@Sections.AsQueryable()">
|
||||
<PropertyColumn Property="@(x => x.Name)" Title="Name" />
|
||||
<PropertyColumn Property="@(x => x.Title)" Title="Title" />
|
||||
<PropertyColumn Property="@(x => x.Preview)" Title="Preview" />
|
||||
</FluentDataGrid>
|
||||
}
|
||||
</div>
|
||||
</FluentCard>
|
||||
|
||||
@code {
|
||||
private readonly List<OperationalReportSection> Sections = new();
|
||||
private string ReportStateLabel = "DATA_MISSING";
|
||||
private string ReportChipLabel = "DATA_MISSING";
|
||||
private string SectionCountLabel = "0";
|
||||
private string GeneratedAtLabel = "n/a";
|
||||
private string SourceLabel = "n/a";
|
||||
private string DecisionFeedLabel = "DISCONNECTED";
|
||||
private string FactorFeedLabel = "DISCONNECTED";
|
||||
private string RawFeedLabel = "DISCONNECTED";
|
||||
private string ReportPath = "n/a";
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
ReportPath = Path.GetFullPath(Path.Combine(Environment.ContentRootPath, "..", "..", "..", "Temp", "operational_report.json"));
|
||||
var report = OperationalReportLoader.Load(ReportPath);
|
||||
Sections.AddRange(report.Sections);
|
||||
SectionCountLabel = report.SectionCount.ToString();
|
||||
GeneratedAtLabel = report.GeneratedAt;
|
||||
SourceLabel = report.SourceJson;
|
||||
ReportStateLabel = Sections.Count > 0 ? "READY" : "DATA_MISSING";
|
||||
ReportChipLabel = Sections.Count > 0 ? "READY" : "DATA_MISSING";
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
@page "/operations"
|
||||
@using QuantEngine.Core.Infrastructure
|
||||
@inject IWebHostEnvironment Environment
|
||||
|
||||
<PageTitle>Quant Engine - Operations</PageTitle>
|
||||
|
||||
<h1 style="margin: 0 0 8px 0; font-size: 28px; font-weight: 600;">Operational Report</h1>
|
||||
<p style="margin: 0 0 16px 0; color: var(--neutral-foreground-2); font-size: 14px;">
|
||||
이 페이지는 `Temp/operational_report.json`만 읽습니다. DB 연결과 무관하게 동일한 결과를 보여주는 운영 고정 화면입니다.
|
||||
</p>
|
||||
|
||||
<!-- Metadata Cards -->
|
||||
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="16" Wrap="true" Style="margin-bottom: 16px;">
|
||||
<FluentCard Style="flex: 1; min-width: 150px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Schema</p>
|
||||
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@SchemaVersion</h3>
|
||||
</div>
|
||||
</FluentCard>
|
||||
<FluentCard Style="flex: 1; min-width: 150px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Sections</p>
|
||||
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@SectionCountLabel</h3>
|
||||
</div>
|
||||
</FluentCard>
|
||||
<FluentCard Style="flex: 1; min-width: 150px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Source</p>
|
||||
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@SourceJson</h3>
|
||||
</div>
|
||||
</FluentCard>
|
||||
<FluentCard Style="flex: 1; min-width: 150px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Generated</p>
|
||||
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@GeneratedAt</h3>
|
||||
</div>
|
||||
</FluentCard>
|
||||
</FluentStack>
|
||||
|
||||
<!-- Highlight Sections Grid -->
|
||||
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="16" Wrap="true" Style="margin-bottom: 16px;">
|
||||
@foreach (var section in HighlightSections)
|
||||
{
|
||||
<FluentCard Style="flex: 1; min-width: 200px;">
|
||||
<div style="padding: 16px;">
|
||||
<p style="margin: 0 0 4px 0; color: var(--neutral-foreground-2); font-size: 12px;">@(section.Name)</p>
|
||||
<h3 style="margin: 4px 0; font-size: 16px; font-weight: 600;">@(section.Title)</h3>
|
||||
<p style="margin: 8px 0 0 0; color: var(--neutral-foreground-3); font-size: 12px;">@(section.Preview)</p>
|
||||
</div>
|
||||
</FluentCard>
|
||||
}
|
||||
</FluentStack>
|
||||
|
||||
<!-- Report Health -->
|
||||
<FluentCard Style="margin-bottom: 16px;">
|
||||
<div style="padding: 16px;">
|
||||
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Report Health</h3>
|
||||
<FluentStack Orientation="Orientation.Vertical" VerticalGap="8">
|
||||
<p style="margin: 0; font-size: 14px;"><strong>Status:</strong> <FluentBadge Appearance="BadgeAppearance.Filled">@HealthLabel</FluentBadge></p>
|
||||
<p style="margin: 0; font-size: 14px;"><strong>Path:</strong> @ReportPath</p>
|
||||
<p style="margin: 0; font-size: 14px;"><strong>Sections rendered:</strong> @RenderedSectionCountLabel</p>
|
||||
</FluentStack>
|
||||
</div>
|
||||
</FluentCard>
|
||||
|
||||
<!-- Sections Table -->
|
||||
<FluentCard>
|
||||
<div style="padding: 16px;">
|
||||
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Sections</h3>
|
||||
@if (Sections.Count == 0)
|
||||
{
|
||||
<div style="padding: 12px; background: var(--warning-background-1); border: 1px solid var(--warning-stroke-1); border-radius: 4px; color: var(--warning-foreground-1); font-size: 14px;">
|
||||
DATA_MISSING: operational_report.json에 표시할 섹션이 없습니다.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<FluentDataGrid Items="@Sections.AsQueryable()">
|
||||
<PropertyColumn Property="@(x => x.Name)" Title="Name" />
|
||||
<PropertyColumn Property="@(x => x.Title)" Title="Title" />
|
||||
<PropertyColumn Property="@(x => x.Preview)" Title="Preview" />
|
||||
</FluentDataGrid>
|
||||
}
|
||||
</div>
|
||||
</FluentCard>
|
||||
|
||||
@code {
|
||||
private readonly List<OperationalReportSection> Sections = new();
|
||||
private readonly List<OperationalReportSection> HighlightSections = new();
|
||||
private string SchemaVersion = "n/a";
|
||||
private string SourceJson = "n/a";
|
||||
private string GeneratedAt = "n/a";
|
||||
private string SectionCountLabel = "0";
|
||||
private string RenderedSectionCountLabel = "0";
|
||||
private string HealthLabel = "DATA_MISSING";
|
||||
private string ReportPath = "n/a";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ReportPath = Path.GetFullPath(Path.Combine(Environment.ContentRootPath, "..", "..", "..", "Temp", "operational_report.json"));
|
||||
|
||||
var report = OperationalReportLoader.Load(ReportPath);
|
||||
SchemaVersion = report.SchemaVersion;
|
||||
SourceJson = report.SourceJson;
|
||||
GeneratedAt = report.GeneratedAt;
|
||||
Sections.AddRange(report.Sections);
|
||||
|
||||
HighlightSections.Clear();
|
||||
HighlightSections.AddRange(Sections.Take(4));
|
||||
|
||||
SectionCountLabel = report.SectionCount.ToString();
|
||||
RenderedSectionCountLabel = Sections.Count.ToString();
|
||||
HealthLabel = Sections.Count > 0 ? "PASS" : "DATA_MISSING";
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,16 @@
|
||||
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
|
||||
<FocusOnNavigate RouteData="routeData" Selector="h1" />
|
||||
</Found>
|
||||
</Router>
|
||||
@using QuantEngine.Web.Client
|
||||
@using QuantEngine.Web.Client.Pages
|
||||
@using QuantEngine.Web.Client.Layout
|
||||
|
||||
<CascadingAuthenticationState>
|
||||
<Router AppAssembly="typeof(Dashboard).Assembly" NotFoundPage="typeof(NotFound)">
|
||||
<Found Context="routeData">
|
||||
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)">
|
||||
<NotAuthorized>
|
||||
<RedirectToLogin />
|
||||
</NotAuthorized>
|
||||
</AuthorizeRouteView>
|
||||
<FocusOnNavigate RouteData="routeData" Selector="h1" />
|
||||
</Found>
|
||||
</Router>
|
||||
</CascadingAuthenticationState>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@@ -6,8 +6,10 @@
|
||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using Microsoft.FluentUI.AspNetCore.Components
|
||||
@using Microsoft.FluentUI.AspNetCore.Components.Icons
|
||||
@using MudBlazor
|
||||
@using QuantEngine.Web
|
||||
@using QuantEngine.Web.Components
|
||||
@using QuantEngine.Web.Components.Layout
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using QuantEngine.Web.Infrastructure
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using QuantEngine.Core.Interfaces;
|
||||
using System.Diagnostics;
|
||||
using QuantEngine.Application.Services;
|
||||
|
||||
namespace QuantEngine.Web.Endpoints;
|
||||
|
||||
@@ -108,51 +108,30 @@ public static class CollectionEndpoints
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IResult> StartCollectionRun(ICollectionRepository repo, ILogger<Program> logger)
|
||||
private static async Task<IResult> StartCollectionRun(
|
||||
DataCollectionService collectionService,
|
||||
HttpRequest request,
|
||||
ILogger<Program> logger)
|
||||
{
|
||||
try
|
||||
{
|
||||
var runId = Guid.NewGuid().ToString("N");
|
||||
var now = DateTime.UtcNow.ToString("o");
|
||||
|
||||
var run = new CollectionRunRecord(
|
||||
RunId: runId,
|
||||
Status: "running",
|
||||
StartedAt: now,
|
||||
FinishedAt: null,
|
||||
TotalSnapshots: null,
|
||||
TotalErrors: null,
|
||||
UpdatedAt: now
|
||||
);
|
||||
var body = await request.ReadFromJsonAsync<CollectionRunRequest>();
|
||||
var account = body?.Account ?? "real";
|
||||
var tickers = body?.Tickers ?? new List<string> { "005930", "000660" };
|
||||
|
||||
await repo.SaveRunAsync(run);
|
||||
|
||||
// Temp: Invoke Python subprocess for actual collection
|
||||
// Trigger async collection (fire-and-forget)
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "python",
|
||||
Arguments = "tools/run_kis_data_collection_v1.py --input-json GatherTradingData.json --sqlite-db src/quant_engine/kis_data_collection.db --kis-account real",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
await process.WaitForExitAsync();
|
||||
|
||||
await repo.UpdateRunStatusAsync(runId, "completed", DateTime.UtcNow.ToString("o"), 0, 0);
|
||||
await collectionService.RunCollectionAsync(runId, account, tickers);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, $"Collection run {runId} failed");
|
||||
await repo.UpdateRunStatusAsync(runId, "failed", DateTime.UtcNow.ToString("o"), null, null);
|
||||
logger.LogError(ex, "Collection run {RunId} failed", runId);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -160,12 +139,20 @@ public static class CollectionEndpoints
|
||||
{
|
||||
runId,
|
||||
status = "running",
|
||||
startedAt = now
|
||||
startedAt = now,
|
||||
tickerCount = tickers.Count
|
||||
});
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Failed to start collection run");
|
||||
return Results.StatusCode(500);
|
||||
}
|
||||
}
|
||||
|
||||
private class CollectionRunRequest
|
||||
{
|
||||
public string? Account { get; set; }
|
||||
public List<string>? Tickers { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,164 +1,2 @@
|
||||
using QuantEngine.Core.Interfaces;
|
||||
|
||||
namespace QuantEngine.Web.Infrastructure;
|
||||
|
||||
/// <summary>
|
||||
/// Placeholder implementations for Collection services.
|
||||
/// Temporary: to be replaced with actual PostgreSQL implementations.
|
||||
/// </summary>
|
||||
|
||||
public class PlaceholderCollectionRepository : ICollectionRepository
|
||||
{
|
||||
private static readonly List<CollectionRunRecord> MockRuns = new();
|
||||
private static readonly List<CollectionSnapshotRecord> MockSnapshots = new();
|
||||
private static readonly List<CollectionErrorRecord> MockErrors = new();
|
||||
|
||||
public Task SaveRunAsync(CollectionRunRecord run)
|
||||
{
|
||||
MockRuns.Add(run);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task UpdateRunStatusAsync(string runId, string status, string? finishedAt = null, int? totalSnapshots = null, int? totalErrors = null)
|
||||
{
|
||||
var run = MockRuns.FirstOrDefault(r => r.RunId == runId);
|
||||
if (run != null)
|
||||
{
|
||||
var idx = MockRuns.IndexOf(run);
|
||||
MockRuns[idx] = new CollectionRunRecord(runId, status, run.StartedAt, finishedAt, totalSnapshots, totalErrors, DateTime.UtcNow.ToString("o"));
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task SaveSnapshotAsync(CollectionSnapshotRecord snapshot)
|
||||
{
|
||||
MockSnapshots.Add(snapshot);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task SaveErrorAsync(CollectionErrorRecord error)
|
||||
{
|
||||
MockErrors.Add(error);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<List<CollectionRunRecord>> GetRecentRunsAsync(int limit = 20)
|
||||
{
|
||||
return Task.FromResult(MockRuns.OrderByDescending(r => r.StartedAt).Take(limit).ToList());
|
||||
}
|
||||
|
||||
public Task<List<CollectionSnapshotRecord>> GetRunSnapshotsAsync(string runId)
|
||||
{
|
||||
return Task.FromResult(MockSnapshots.Where(s => s.RunId == runId).ToList());
|
||||
}
|
||||
|
||||
public Task<List<CollectionErrorRecord>> GetRunErrorsAsync(string runId, int limit = 50)
|
||||
{
|
||||
return Task.FromResult(MockErrors.Where(e => e.RunId == runId).Take(limit).ToList());
|
||||
}
|
||||
|
||||
public Task<CollectionDashboardStateRecord> GetDashboardStateAsync()
|
||||
{
|
||||
var lastRun = MockRuns.OrderByDescending(r => r.StartedAt).FirstOrDefault();
|
||||
var recentErrors = MockErrors.OrderByDescending(e => e.CreatedAt).Take(5).ToList();
|
||||
|
||||
return Task.FromResult(new CollectionDashboardStateRecord(
|
||||
LastRunId: lastRun?.RunId,
|
||||
LastRunStatus: lastRun?.Status,
|
||||
LastFinishedAt: lastRun?.FinishedAt,
|
||||
TotalSnapshots: MockSnapshots.Count,
|
||||
TotalErrors: MockErrors.Count,
|
||||
RecentErrors: recentErrors
|
||||
));
|
||||
}
|
||||
|
||||
public Task<List<CollectionSnapshotRecord>> GetLatestSnapshotsForTickerAsync(string ticker, int limit = 10)
|
||||
{
|
||||
return Task.FromResult(MockSnapshots.Where(s => s.Ticker == ticker).OrderByDescending(s => s.CapturedAt).Take(limit).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
public class PlaceholderTokenCache : ITokenCache
|
||||
{
|
||||
private static readonly Dictionary<string, (string Token, DateTime ExpiresAt)> Cache = new();
|
||||
|
||||
public Task<string?> GetCachedTokenAsync(string account)
|
||||
{
|
||||
if (Cache.TryGetValue(account, out var entry) && entry.ExpiresAt > DateTime.UtcNow.AddMinutes(10))
|
||||
{
|
||||
return Task.FromResult<string?>(entry.Token);
|
||||
}
|
||||
return Task.FromResult<string?>(null);
|
||||
}
|
||||
|
||||
public Task SaveTokenAsync(string account, string token, DateTime expiresAt)
|
||||
{
|
||||
Cache[account] = (token, expiresAt);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task ClearExpiredTokensAsync()
|
||||
{
|
||||
var expired = Cache.Where(kv => kv.Value.ExpiresAt <= DateTime.UtcNow).Select(kv => kv.Key).ToList();
|
||||
foreach (var key in expired) Cache.Remove(key);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
public class PlaceholderKisApiClient : IKisApiClient
|
||||
{
|
||||
public Task<Dictionary<string, object>> GetCurrentPriceAsync(string code, string account = "mock")
|
||||
{
|
||||
return Task.FromResult(new Dictionary<string, object>
|
||||
{
|
||||
{ "code", code },
|
||||
{ "price", 0 },
|
||||
{ "change", 0 },
|
||||
{ "changeRate", 0 }
|
||||
});
|
||||
}
|
||||
|
||||
public Task<Dictionary<string, object>> GetAskingPrice10LevelAsync(string code, string account = "mock")
|
||||
{
|
||||
return Task.FromResult(new Dictionary<string, object>
|
||||
{
|
||||
{ "code", code },
|
||||
{ "askLevels", new List<object>() },
|
||||
{ "bidLevels", new List<object>() }
|
||||
});
|
||||
}
|
||||
|
||||
public Task<Dictionary<string, object>> GetDailyShortSaleAsync(string code, string startDate, string endDate, string account = "mock")
|
||||
{
|
||||
return Task.FromResult(new Dictionary<string, object>
|
||||
{
|
||||
{ "code", code },
|
||||
{ "startDate", startDate },
|
||||
{ "endDate", endDate },
|
||||
{ "data", new List<object>() }
|
||||
});
|
||||
}
|
||||
|
||||
public Task<Dictionary<string, object>> GetDailyItemChartPriceAsync(string code, string startDate, string endDate, string period = "D", string account = "mock")
|
||||
{
|
||||
return Task.FromResult(new Dictionary<string, object>
|
||||
{
|
||||
{ "code", code },
|
||||
{ "startDate", startDate },
|
||||
{ "endDate", endDate },
|
||||
{ "period", period },
|
||||
{ "candles", new List<object>() }
|
||||
});
|
||||
}
|
||||
|
||||
public Task<Dictionary<string, object>> GetInvestorTrendAsync(string code, string account = "mock")
|
||||
{
|
||||
return Task.FromResult(new Dictionary<string, object>
|
||||
{
|
||||
{ "code", code },
|
||||
{ "individual", 0 },
|
||||
{ "foreign", 0 },
|
||||
{ "institution", 0 }
|
||||
});
|
||||
}
|
||||
}
|
||||
// Placeholder implementations removed — using PostgreSQL-backed real implementations instead.
|
||||
// See Program.cs for service registration.
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
using QuantEngine.Web.Components;
|
||||
using QuantEngine.Web.Services;
|
||||
using QuantEngine.Infrastructure.Data;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using QuantEngine.Web.Infrastructure;
|
||||
using QuantEngine.Infrastructure.Repositories;
|
||||
using QuantEngine.Infrastructure.Services;
|
||||
using QuantEngine.Core.Interfaces;
|
||||
using QuantEngine.Application.Services;
|
||||
using System.Text.Json;
|
||||
using Microsoft.FluentUI.AspNetCore.Components;
|
||||
using static QuantEngine.Application.Services.DataCollectionService;
|
||||
using Serilog;
|
||||
using QuantEngine.Web.Infrastructure;
|
||||
using QuantEngine.Web.Client.Infrastructure;
|
||||
using QuantEngine.Web.Client.Services;
|
||||
using QuantEngine.Web.Endpoints;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using QuantEngine.Core.Models;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MudBlazor.Services;
|
||||
|
||||
// Serilog Configuration with Telegram Sink
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
@@ -23,33 +32,74 @@ builder.Host.UseSerilog();
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents();
|
||||
.AddInteractiveWebAssemblyComponents();
|
||||
|
||||
// Fluent UI Services
|
||||
builder.Services.AddFluentUIComponents();
|
||||
// Authentication and Custom State Provider (Shared client components)
|
||||
builder.Services.AddCascadingAuthenticationState();
|
||||
builder.Services.AddAuthentication("QuantAdminScheme")
|
||||
.AddScheme<AuthenticationSchemeOptions, QuantAdminAuthHandler>("QuantAdminScheme", _ => { });
|
||||
builder.Services.AddAuthorization();
|
||||
builder.Services.AddScoped<LocalStorageService>();
|
||||
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
|
||||
builder.Services.AddAuthorizationCore();
|
||||
|
||||
builder.Services.AddMudServices();
|
||||
|
||||
// PostgreSQL Dapper Setup
|
||||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
|
||||
?? "Host=127.0.0.1;Database=giteadb;Username=gitea;Password=C8RFlZ9fdQrBA1vyLhLDS4v70I8dJfRS2ERJW4+zsS4=;Search Path=quantengine;";
|
||||
var configuredConnectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
||||
var fallbackConnectionString = "Host=127.0.0.1;Database=quantenginedb;Username=quantengine_app;Password=CHANGE_ME;Search Path=quantengine;";
|
||||
var connectionString = string.IsNullOrWhiteSpace(configuredConnectionString) || configuredConnectionString.Contains("Password=;", StringComparison.OrdinalIgnoreCase)
|
||||
? fallbackConnectionString
|
||||
: configuredConnectionString;
|
||||
var configuredDatabase = new Npgsql.NpgsqlConnectionStringBuilder(connectionString).Database;
|
||||
if (!string.Equals(configuredDatabase, "quantenginedb", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException("QuantEngine must use the quantenginedb PostgreSQL database.");
|
||||
}
|
||||
builder.Services.AddSingleton<IDbConnectionFactory>(new DbConnectionFactory(connectionString));
|
||||
builder.Services.AddSingleton<DbMigrator>();
|
||||
builder.Services.AddScoped<IWorkspaceRepository, WorkspaceRepository>();
|
||||
builder.Services.AddScoped<IPostgresqlHistoryStore, PostgresqlHistoryStore>();
|
||||
builder.Services.AddScoped<IPostgresqlHistorySnapshotReader, PostgresqlHistorySnapshotReader>();
|
||||
builder.Services.AddScoped<HistoryIngestionService>();
|
||||
|
||||
// Collection Pipeline Services (using placeholder implementations for now)
|
||||
builder.Services.AddScoped<ICollectionRepository, PlaceholderCollectionRepository>();
|
||||
builder.Services.AddScoped<ITokenCache, PlaceholderTokenCache>();
|
||||
builder.Services.AddScoped<IKisApiClient, PlaceholderKisApiClient>();
|
||||
// Collection Pipeline Services (PostgreSQL-backed implementations)
|
||||
builder.Services.AddScoped<ICollectionRepository, CollectionRepository>();
|
||||
builder.Services.AddScoped<ITokenCache, PostgresTokenCache>();
|
||||
builder.Services.AddScoped<IKisApiClient, KisApiClient>();
|
||||
builder.Services.AddScoped<DataCollectionService>();
|
||||
|
||||
// HTTP Client & API Services
|
||||
builder.Services.AddHttpClient<ApiClient>();
|
||||
builder.Services.AddScoped<ApiClient>();
|
||||
|
||||
var app = builder.Build();
|
||||
var adminSettings = app.Configuration.GetSection("AdminSettings");
|
||||
var adminUsername = adminSettings["Username"] ?? "admin";
|
||||
var adminPassword = adminSettings["Password"] ?? string.Empty;
|
||||
|
||||
// Enable reverse proxy subpath mapping
|
||||
app.UsePathBase("/quant");
|
||||
// Initialize database tables (PostgreSQL-backed repositories)
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var migrator = scope.ServiceProvider.GetRequiredService<DbMigrator>();
|
||||
var tokenCache = scope.ServiceProvider.GetRequiredService<ITokenCache>();
|
||||
var collectionRepo = scope.ServiceProvider.GetRequiredService<ICollectionRepository>();
|
||||
var workspaceRepo = scope.ServiceProvider.GetRequiredService<IWorkspaceRepository>();
|
||||
|
||||
try
|
||||
{
|
||||
migrator.Migrate();
|
||||
// Ensure tables exist on startup
|
||||
await tokenCache.GetCachedTokenAsync("_init_test_");
|
||||
await collectionRepo.GetDashboardStateAsync();
|
||||
await workspaceRepo.GetAccountsAsync();
|
||||
Log.Information("Database tables initialized successfully");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning($"Database initialization warning: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
@@ -67,12 +117,186 @@ app.UseStatusCodePages(async ctx =>
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAntiforgery();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapStaticAssets();
|
||||
|
||||
app.MapGet("/", () => Results.Redirect("/login"));
|
||||
|
||||
// Collection API Endpoints (must be before MapRazorComponents)
|
||||
app.MapCollectionEndpoints();
|
||||
|
||||
// Login API (API-First for Blazor WASM client authentication)
|
||||
app.MapPost("/api/auth/login", async (JsonElement payload, IWorkspaceRepository workspaceRepo) =>
|
||||
{
|
||||
static string? ReadString(JsonElement root, params string[] names)
|
||||
{
|
||||
foreach (var name in names)
|
||||
{
|
||||
if (root.ValueKind == JsonValueKind.Object && root.TryGetProperty(name, out var property) && property.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
return property.GetString();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var username = ReadString(payload, "Username", "username");
|
||||
var password = ReadString(payload, "Password", "password");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
|
||||
{
|
||||
return Results.BadRequest(new { success = false, error = "missing_credentials" });
|
||||
}
|
||||
|
||||
var account = await workspaceRepo.GetAccountByUsernameAsync(username.Trim());
|
||||
if (account is null || !string.Equals(account.IsActive, "true", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Results.Json(new { success = false, error = "invalid_credentials" }, statusCode: 401);
|
||||
}
|
||||
|
||||
var passwordHash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(password)));
|
||||
if (!string.Equals(account.PasswordHash, passwordHash, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Results.Json(new { success = false, error = "invalid_credentials" }, statusCode: 401);
|
||||
}
|
||||
|
||||
var rawToken = Guid.NewGuid().ToString("N");
|
||||
var tokenHash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(rawToken)));
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var expiresAt = now.AddDays(7);
|
||||
|
||||
await workspaceRepo.UpsertSessionAsync(new WorkspaceSession
|
||||
{
|
||||
SessionTokenHash = tokenHash,
|
||||
Username = account.Username,
|
||||
Role = account.Role,
|
||||
CreatedAt = now.ToString("O"),
|
||||
ExpiresAt = expiresAt.ToString("O"),
|
||||
RevokedAt = null
|
||||
});
|
||||
|
||||
return Results.Ok(new
|
||||
{
|
||||
success = true,
|
||||
username = account.Username,
|
||||
role = account.Role,
|
||||
accessToken = rawToken,
|
||||
expiresAt = expiresAt.ToString("O")
|
||||
});
|
||||
}).DisableAntiforgery();
|
||||
|
||||
app.MapGet("/api/auth/me", async (HttpContext context, IWorkspaceRepository workspaceRepo) =>
|
||||
{
|
||||
var authHeader = context.Request.Headers.Authorization.ToString();
|
||||
if (string.IsNullOrWhiteSpace(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Results.Unauthorized();
|
||||
}
|
||||
|
||||
var token = authHeader["Bearer ".Length..].Trim();
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
{
|
||||
return Results.Unauthorized();
|
||||
}
|
||||
|
||||
var tokenHash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(token)));
|
||||
var session = await workspaceRepo.GetSessionByTokenHashAsync(tokenHash);
|
||||
if (session is null || !string.IsNullOrWhiteSpace(session.RevokedAt) || DateTimeOffset.TryParse(session.ExpiresAt, out var expiresAt) && expiresAt <= DateTimeOffset.UtcNow)
|
||||
{
|
||||
return Results.Unauthorized();
|
||||
}
|
||||
|
||||
return Results.Ok(new { authenticated = true, username = session.Username, role = session.Role });
|
||||
});
|
||||
|
||||
app.MapPost("/api/auth/logout", async (HttpContext context, IWorkspaceRepository workspaceRepo) =>
|
||||
{
|
||||
var authHeader = context.Request.Headers.Authorization.ToString();
|
||||
if (string.IsNullOrWhiteSpace(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Results.Unauthorized();
|
||||
}
|
||||
|
||||
var token = authHeader["Bearer ".Length..].Trim();
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
{
|
||||
return Results.Unauthorized();
|
||||
}
|
||||
|
||||
var tokenHash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(token)));
|
||||
await workspaceRepo.RevokeSessionAsync(tokenHash, DateTimeOffset.UtcNow.ToString("O"));
|
||||
return Results.Ok(new { success = true });
|
||||
}).DisableAntiforgery();
|
||||
|
||||
app.MapPost("/api/auth/admin/reset-password", async (HttpContext context, JsonElement payload, IWorkspaceRepository workspaceRepo) =>
|
||||
{
|
||||
static string? ReadString(JsonElement root, params string[] names)
|
||||
{
|
||||
foreach (var name in names)
|
||||
{
|
||||
if (root.ValueKind == JsonValueKind.Object && root.TryGetProperty(name, out var property) && property.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
return property.GetString();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var username = ReadString(payload, "adminUsername", "AdminUsername", "username", "Username");
|
||||
var password = ReadString(payload, "adminPassword", "AdminPassword", "password", "Password");
|
||||
var targetUsername = ReadString(payload, "targetUsername", "TargetUsername", "usernameToReset", "UsernameToReset");
|
||||
var newPassword = ReadString(payload, "newPassword", "NewPassword");
|
||||
|
||||
if (!string.Equals(username, adminUsername, StringComparison.Ordinal) || !string.Equals(password, adminPassword, StringComparison.Ordinal))
|
||||
{
|
||||
return Results.Unauthorized();
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(targetUsername) || string.IsNullOrWhiteSpace(newPassword))
|
||||
{
|
||||
return Results.BadRequest(new { success = false, error = "missing_target_or_password" });
|
||||
}
|
||||
|
||||
var account = await workspaceRepo.GetAccountByUsernameAsync(targetUsername.Trim());
|
||||
if (account is null)
|
||||
{
|
||||
return Results.NotFound(new { success = false, error = "account_not_found" });
|
||||
}
|
||||
|
||||
var passwordHash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(newPassword)));
|
||||
account.PasswordHash = passwordHash;
|
||||
account.UpdatedAt = DateTimeOffset.UtcNow.ToString("O");
|
||||
var updated = await workspaceRepo.UpsertAccountAsync(account);
|
||||
if (!updated)
|
||||
{
|
||||
return Results.StatusCode(500);
|
||||
}
|
||||
|
||||
return Results.Ok(new
|
||||
{
|
||||
success = true,
|
||||
username = account.Username,
|
||||
updatedAt = account.UpdatedAt
|
||||
});
|
||||
}).DisableAntiforgery();
|
||||
|
||||
// Operational Report serving API (WASM safe file loading substitute)
|
||||
app.MapGet("/api/operational-report", async (IWebHostEnvironment env) =>
|
||||
{
|
||||
var path = Path.GetFullPath(Path.Combine(env.ContentRootPath, "..", "..", "..", "Temp", "operational_report.json"));
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return Results.NotFound(new { gate = "FAIL", error = "operational_report_missing" });
|
||||
}
|
||||
var json = await File.ReadAllTextAsync(path);
|
||||
using var doc = JsonDocument.Parse(json);
|
||||
return Results.Ok(doc.RootElement);
|
||||
});
|
||||
|
||||
app.MapGet("/api/history/{domain}", async (string domain, int? limit, IPostgresqlHistorySnapshotReader reader) =>
|
||||
{
|
||||
var rows = await reader.ReadAsync(domain, limit ?? 500);
|
||||
@@ -117,7 +341,30 @@ app.MapPost("/api/history/{domain}", async (string domain, JsonElement payload,
|
||||
});
|
||||
|
||||
app.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode();
|
||||
.AddInteractiveWebAssemblyRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(QuantEngine.Web.Client._Imports).Assembly);
|
||||
|
||||
app.Run();
|
||||
|
||||
internal sealed class QuantAdminAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
|
||||
{
|
||||
public QuantAdminAuthHandler(
|
||||
IOptionsMonitor<AuthenticationSchemeOptions> options,
|
||||
ILoggerFactory logger,
|
||||
UrlEncoder encoder)
|
||||
: base(options, logger, encoder)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
{
|
||||
return Task.FromResult(AuthenticateResult.NoResult());
|
||||
}
|
||||
|
||||
protected override Task HandleChallengeAsync(AuthenticationProperties properties)
|
||||
{
|
||||
Response.StatusCode = StatusCodes.Status401Unauthorized;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,12 +4,21 @@
|
||||
<ProjectReference Include="..\QuantEngine.Infrastructure\QuantEngine.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\QuantEngine.Application\QuantEngine.Application.csproj" />
|
||||
<ProjectReference Include="..\QuantEngine.Core\QuantEngine.Core.csproj" />
|
||||
<ProjectReference Include="Client\QuantEngine.Web.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.FluentUI.AspNetCore.Components" Version="5.0.0-rc.4-26177.1" />
|
||||
<PackageReference Include="Microsoft.FluentUI.AspNetCore.Components.Icons" Version="5.0.0-rc.4-26177.1" />
|
||||
<PackageReference Include="MudBlazor" Version="8.6.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.0-preview.2.25120.18" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Exclude client project files from server build to avoid duplicate compilations -->
|
||||
<Compile Remove="Client\**" />
|
||||
<Content Remove="Client\**" />
|
||||
<EmbeddedResource Remove="Client\**" />
|
||||
<None Remove="Client\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=127.0.0.1;Database=giteadb;Username=gitea;Password=;Search Path=quantengine;"
|
||||
"DefaultConnection": "Host=127.0.0.1;Database=quantenginedb;Username=quantengine_app;Password=;Search Path=quantengine;"
|
||||
},
|
||||
"AdminSettings": {
|
||||
"Username": "admin",
|
||||
"Password": "quant123!"
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user