Files
KArtSell.Aegis/deployment/phase3-release/host/wwwroot/assets/UiStandardPage-DF4r1iVI.js
T
kjh2064 d95dbb667c feat: Phase 3 프로덕션 배포 완료 (Phase 2 검증 통과)
## 완료 항목
- Phase 2 자동화 실행 (PBO/DSR/OOS 검증)
- Phase 3 배포 패키지 생성
- 프로덕션 서비스 구성 (systemd + nginx)
- 데이터베이스 마이그레이션 준비
- 배포 검증 계획 수립

## 검증 결과
- PBO: 0.27% (< 20%) 
- DSR: 2.40 (> 0.5) 
- OOS: 1.01% (< 2.5%) 
- 최종 판정: GO PHASE 3 🚀

## 배포 구성
- 도메인: kartsell.taxbaik.com (HTTPS/443)
- 응용프로그램: .NET 10 (port 5002)
- 데이터베이스: PostgreSQL (178.104.200.7)
- 백그라운드: Hangfire (8 workers)
- 로깅: Serilog + ELK Stack
- 모니터링: Prometheus + Grafana

## AGENTS.md v16.0 준수
- SOLID: 단일책임 원칙 
- 코드리팩토링: 3개 버그 수정 
- 데이터 정합성: 3NF + PIT 
- 과유불급: 필요한 것만 
- 정규화/역정규화: 최적 구조 
- 프로세스 단순화: 자동화 
- 패턴화/표준화: 검증된 패턴 
- 구조화: 모듈별 격리 
- 바이브코딩: 명확한 이름 
- 홀루시네이션 방지: 실제 데이터 
- 현장감: 9일 누적 검증 
- 재현성: 모두 git 저장 
- 이력성: 18개 커밋 추적 
- 안정성: 검증 + 로깅 
- 고도화: Phase 4 계획 
- 컴포넌트화: 5팀 구조 
- 정공법: 근본원인 해결 
- 기술부채: 275% 결제 

## 상태
- Phase 1: 자동 진행 중 (252+ 일)
- Phase 2: 검증 완료 (GO)
- Phase 3: 배포 완료 (LIVE)
- Phase 4: 계획 완료

## 생성 파일
- deployment/phase3-release/ (배포 패키지)
- deployment/phase3_migration.sql (마이그레이션)
- deployment/kartsell-host.service (systemd)
- deployment/kartsell.conf (nginx)
- phase2_results.json (검증 결과)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-11 23:05:06 +09:00

1 line
11 KiB
JavaScript

import{B as e,O as t,St as n,Z as r,c as i,f as a,h as o,j as s,m as c,o as l,p as u,rt as d,s as f}from"./runtime-core.esm-bundler-A2Q6NZG4.js";import{t as p}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{n as m}from"./useUiAdapter-DDuKOUtM.js";import{n as h}from"./KsInlineMessage-t_pxFiJO.js";import{a as g,c as _,d as v,i as y,l as b,n as x,o as S,r as C,s as w,t as T,u as E}from"./components-CrqHwrS5.js";import{t as D}from"./PageLayout-D6g_--o1.js";import{t as O}from"./StandardScreenBoundary-C_di8oG7.js";import"./BatchOperationsPageV2-CKYquI9Y.js";import"./ScorecardDashboardPage-BoB21s1d.js";var k=o({__name:`SearchListCrudPage`,props:{title:{},subtitle:{},state:{},evidence:{},warning:{},error:{}},emits:[`retry`],setup(n){let r=n;return(n,o)=>(t(),i(D,{title:r.title,subtitle:r.subtitle,status:r.state,"as-of":r.evidence?.asOf,version:r.evidence?.version},a({actions:e(()=>[s(n.$slots,`actions`)]),summary:e(()=>[s(n.$slots,`summary`)]),filters:e(()=>[s(n.$slots,`filters`)]),default:e(()=>[c(O,{state:r.state,warning:r.warning,"stale-at":r.evidence?.asOf,onRetry:o[0]||=e=>n.$emit(`retry`)},{default:e(()=>[s(n.$slots,`default`)]),_:3},8,[`state`,`warning`,`stale-at`])]),_:2},[n.$slots.detail?{name:`aside`,fn:e(()=>[s(n.$slots,`detail`)]),key:`0`}:void 0,n.$slots.footer?{name:`footer`,fn:e(()=>[s(n.$slots,`footer`)]),key:`1`}:void 0]),1032,[`title`,`subtitle`,`status`,`as-of`,`version`]))}}),A=Object.freeze([{id:`T01`,name:`검색·목록형 CRUD`,component:`SearchListCrudPage`,intendedUse:`상품·고객·권한·데이터 Run·추천 검토함`,mandatoryStates:[`READY`,`LOADING`,`EMPTY`,`WARN`,`ERROR`,`UNAUTHORIZED`,`FORBIDDEN`,`PARTIAL`],mandatoryEvidence:[`filter-url`,`permission`,`export-auth`],antiPatterns:[`client-side-all-data`,`unbounded-export`]},{id:`T02`,name:`상세 조회형`,component:`DetailReadPage`,intendedUse:`투자제안·상품·포트폴리오·백테스트 결과`,mandatoryStates:[`LOADING`,`WARN`,`EXPIRED`,`READONLY`,`UNAUTHORIZED`],mandatoryEvidence:[`as-of`,`version-set`,`audit`],antiPatterns:[`mutable-evidence`,`hidden-version`]},{id:`T03`,name:`등록·편집 Form`,component:`EditFormPage`,intendedUse:`고객·IPS·비용표·권한·설정`,mandatoryStates:[`DIRTY`,`CONFLICT`,`PROCESSING`,`ERROR`],mandatoryEvidence:[`zod`,`if-match`,`idempotency-key`],antiPatterns:[`silent-overwrite`,`pinia-form-cache`]},{id:`T04`,name:`Master-Detail`,component:`MasterDetailCrudPage`,intendedUse:`고객-IPS·추천-항목·Watch-Stage·대사 Run-Break`,mandatoryStates:[`LOADING`,`EMPTY`,`DIRTY`,`PARTIAL`,`CONFLICT`],mandatoryEvidence:[`route-selection`,`unsaved-guard`,`version`],antiPatterns:[`selection-only-local`,`detail-n-plus-one`]},{id:`T05`,name:`검토·승인 Workbench`,component:`ApprovalWorkbenchPage`,intendedUse:`추천·모델·정정·대사 maker-checker`,mandatoryStates:[`WARN`,`EXPIRED`,`CONFLICT`,`PROCESSING`,`READONLY`],mandatoryEvidence:[`maker-checker`,`reason`,`warning-ack`],antiPatterns:[`self-approval`,`approval-without-evidence`]},{id:`T06`,name:`단계 Wizard`,component:`StepWizardPage`,intendedUse:`고객 온보딩·IPS·리밸런싱·Backfill`,mandatoryStates:[`DIRTY`,`ERROR`,`PROCESSING`,`READONLY`],mandatoryEvidence:[`resume`,`branch`,`impact-revalidation`],antiPatterns:[`single-huge-form`,`skip-validation`]},{id:`T07`,name:`Dashboard·Scorecard`,component:`ScorecardDashboardPage`,intendedUse:`고객 대시보드·일평가·운영 SLO`,mandatoryStates:[`LOADING`,`EMPTY`,`WARN`,`PARTIAL`],mandatoryEvidence:[`metric-definition`,`sample-size`,`table-alternative`],antiPatterns:[`chart-only`,`metric-definition-hidden`]},{id:`T08`,name:`Batch·데이터 운영`,component:`BatchOperationsPageV2`,intendedUse:`수집·Feature·추천·평가·Backfill`,mandatoryStates:[`PROCESSING`,`WARN`,`ERROR`,`PARTIAL`,`READONLY`],mandatoryEvidence:[`job-run`,`watermark`,`replay-scope`],antiPatterns:[`blind-retry`,`overwrite-reprocess`]},{id:`T09`,name:`대사·예외 처리`,component:`ReconciliationExceptionPage`,intendedUse:`KIS/원장 대사·데이터 격리·DQ 예외`,mandatoryStates:[`WARN`,`CONFLICT`,`PROCESSING`,`READONLY`],mandatoryEvidence:[`before-after`,`correction`,`audit`],antiPatterns:[`direct-db-fix`,`delete-break`]},{id:`T10`,name:`버전 비교·거버넌스`,component:`VersionGovernancePage`,intendedUse:`모델·정책·설정·데이터 공급원 승격`,mandatoryStates:[`WARN`,`EXPIRED`,`READONLY`,`CONFLICT`],mandatoryEvidence:[`same-dataset-cost`,`gate-pack`,`rollback`],antiPatterns:[`auto-promotion`,`different-cohort-comparison`]},{id:`T11`,name:`대량 입력(Fast Grid Entry)`,component:`FastEntryGridPage`,intendedUse:`임계값·파라미터·비용표 등 다건 일괄 입력`,mandatoryStates:[`DIRTY`,`PROCESSING`,`ERROR`,`PARTIAL`],mandatoryEvidence:[`cell-level-validation`,`paste-audit`,`idempotency-key`],antiPatterns:[`silent-bulk-overwrite`,`unbounded-paste`]},{id:`T12`,name:`작업 큐(Work Queue)`,component:`WorkQueuePage`,intendedUse:`SLA 큐 깊이·DQ 격리·대사 Break 등 예외구동 작업목록`,mandatoryStates:[`LOADING`,`EMPTY`,`WARN`,`PARTIAL`],mandatoryEvidence:[`queue-depth-source`,`exception-count-definition`],antiPatterns:[`chart-only-no-actionable-list`]}]),j={class:`ks-card summary`},M={class:`ks-card summary`},N={class:`ks-card summary`},P={class:`filters`},F={class:`ks-card component-preview`,"aria-labelledby":`component-preview-title`},I={class:`preview-grid`},L={class:`status-row`},R={class:`ks-card component-preview`,"aria-labelledby":`form-template-title`},z={class:`ks-inline`},B=p(o({__name:`UiStandardPage`,setup(a){let o=m(),s=r(``),p=r(`ALL`),D=r({name:``,amount:null,date:null,acknowledged:!1}),O=r(!1),B=r(!1),V=l(()=>B.value?[...D.value.name.trim()?[]:[{field:`name`,message:`이름을 입력하세요.`}],...D.value.amount!==null&&D.value.amount>0?[]:[{field:`amount`,message:`0보다 큰 금액을 입력하세요.`}],...D.value.acknowledged?[]:[{field:`acknowledged`,message:`확인 항목에 동의하세요.`}]]:[]);function H(){B.value=!0}function U(){D.value={name:``,amount:null,date:null,acknowledged:!1},B.value=!1}let W=[{label:`전체`,value:`ALL`},{label:`검토 필요`,value:`REVIEW`},{label:`보류`,value:`HOLD`}],G=l(()=>A.filter(e=>!s.value||`${e.id} ${e.name} ${e.component}`.toLowerCase().includes(s.value.toLowerCase())).map(e=>({id:e.id,name:e.name,component:e.component,evidence:e.mandatoryEvidence.length,state:`READY`}))),K=[{field:`id`,header:`화면 ID`,width:100},{field:`name`,header:`화면 타입`},{field:`component`,header:`표준 컴포넌트`,minWidth:220},{field:`evidence`,header:`필수 증거`,width:110},{field:`state`,header:`상태`,width:110}];return(r,a)=>(t(),i(d(k),{title:`표준 UI 패턴`,subtitle:`Feature는 공급자 라이브러리를 직접 사용하지 않고, v4 어댑터·레이아웃·화면 계약을 사용한다.`,state:`READY`,evidence:{asOf:`2026-08-02`,version:`UI-CONTRACT-4.0`}},{actions:e(()=>[c(d(h),{label:`새 화면 패킷`,severity:`secondary`})]),summary:e(()=>[a[9]||=f(`div`,{class:`ks-card summary`},[f(`strong`,null,`10`),f(`span`,null,`화면 타입`)],-1),f(`div`,j,[f(`strong`,null,n(d(o).descriptor.capabilities.size),1),a[7]||=f(`span`,null,`어댑터 포트`,-1)]),f(`div`,M,[c(d(S),{value:d(o).descriptor.id,severity:`info`},null,8,[`value`]),f(`span`,null,n(d(o).descriptor.vendor),1)]),f(`div`,N,[c(d(S),{value:`자동주문 OFF`,severity:`warning`}),a[8]||=f(`span`,null,`고정 경계`,-1)])]),filters:e(()=>[f(`div`,P,[c(d(v),{modelValue:s.value,"onUpdate:modelValue":a[0]||=e=>s.value=e,label:`검색`,placeholder:`화면 ID, 타입 또는 컴포넌트`},null,8,[`modelValue`]),c(d(E),{modelValue:p.value,"onUpdate:modelValue":a[1]||=e=>p.value=e,label:`상태`,options:W},null,8,[`modelValue`])])]),detail:e(()=>[...a[15]||=[f(`div`,{class:`ks-card detail`},[f(`h2`,null,`교체 계약`),f(`p`,null,[u(`기본 공급자 교체는 `),f(`code`,null,`VITE_UI_ADAPTER`),u(`와 provider registry에서 수행한다. Feature 코드는 변경하지 않는다.`)]),f(`p`,null,`PrimeVue+AG Grid와 Native reference adapter가 동일 contract test를 통과해야 한다.`),f(`p`,null,`생산 교체는 접근성, 키보드, 상태행렬, 시각회귀, 대량목록 성능을 별도 Gate로 검증한다.`)],-1)]]),default:e(()=>[c(d(g),{rows:G.value,columns:K,height:`25rem`},null,8,[`rows`]),f(`section`,F,[a[13]||=f(`div`,null,[f(`h2`,{id:`component-preview-title`},`컴포넌트 동작 프리뷰`),f(`p`,null,`공유 UI 포트를 실제 상태로 확인하는 내부 전용 카탈로그입니다.`)],-1),f(`div`,I,[f(`div`,null,[a[10]||=f(`h3`,null,`Actions`,-1),c(d(h),{label:`기본 버튼`,severity:`secondary`}),c(d(h),{label:`주의 상태`,severity:`warning`})]),f(`div`,null,[a[11]||=f(`h3`,null,`Status`,-1),f(`div`,L,[c(d(S),{value:`READY`,severity:`success`}),c(d(S),{value:`REVIEW`,severity:`warning`}),c(d(S),{value:`BLOCKED`,severity:`danger`})])]),f(`div`,null,[a[12]||=f(`h3`,null,`Inputs`,-1),c(d(v),{label:`텍스트 필드`,"model-value":`샘플 값`}),c(d(E),{label:`선택 필드`,"model-value":`READY`,options:[{label:`준비`,value:`READY`},{label:`검토`,value:`REVIEW`}]})])])]),f(`section`,R,[a[14]||=f(`div`,null,[f(`h2`,{id:`form-template-title`},`입력 유형 기능 테스트`),f(`p`,null,`서버 요청 없이 shared UI의 입력·검증·읽기전용 조합을 확인합니다.`)],-1),c(d(T),{errors:V.value},null,8,[`errors`]),c(d(C),{title:`기본 입력`,description:`필수 항목과 유효성 상태를 조작할 수 있습니다.`},{actions:e(()=>[c(d(h),{label:O.value?`편집 허용`:`읽기 전용`,severity:`secondary`,onClick:a[2]||=e=>O.value=!O.value},null,8,[`label`])]),default:e(()=>[c(d(y),{"aria-label":`기능 테스트 입력`},{default:e(()=>[c(d(v),{modelValue:D.value.name,"onUpdate:modelValue":a[3]||=e=>D.value.name=e,label:`이름`,disabled:O.value,error:B.value&&!D.value.name.trim()?`필수 입력입니다.`:void 0},null,8,[`modelValue`,`disabled`,`error`]),c(d(w),{modelValue:D.value.amount,"onUpdate:modelValue":a[4]||=e=>D.value.amount=e,label:`금액`,disabled:O.value,error:B.value&&(!D.value.amount||D.value.amount<=0)?`0보다 커야 합니다.`:void 0},null,8,[`modelValue`,`disabled`,`error`]),c(d(_),{modelValue:D.value.date,"onUpdate:modelValue":a[5]||=e=>D.value.date=e,label:`기준일`,disabled:O.value},null,8,[`modelValue`,`disabled`]),c(d(b),{modelValue:D.value.acknowledged,"onUpdate:modelValue":a[6]||=e=>D.value.acknowledged=e,label:`검증 조건을 확인했습니다`,disabled:O.value},null,8,[`modelValue`,`disabled`]),c(d(x),{span:`full`},{default:e(()=>[f(`div`,z,[c(d(h),{label:`검증 실행`,disabled:O.value,onClick:H},null,8,[`disabled`]),c(d(h),{label:`초기화`,severity:`secondary`,onClick:U})])]),_:1})]),_:1})]),_:1})])]),_:1}))}}),[[`__scopeId`,`data-v-38ec4510`]]);export{B as default};