# P5-W3 전수 감사 입력 스펙 (PL 작성, 2026-05-17)

목적: 보험 수수료 시스템의 **메뉴/권한/라우트 정합성**을 전수 감사하고 누락분을 전부 보강한다.
PL이 소스에서 직접 추출한 신뢰 가능한 입력 2종을 아래 둔다. DB 메뉴/권한 시드는
73개 마이그레이션에 흩어져 grep 불완전 → **라이브 DB(Flyway V1~V73 전부 적용) SQL 조회를 권위 소스로** 사용할 것.

## 1. 프론트 App.tsx 실제 라우트 (스크린 존재 위치 = 정본)

메뉴 menu_path 는 이 경로와 **정확히 일치**해야 한다. 불일치 시 menu_path/component_path 를 이 값으로 UPDATE.

```
org/tree org/agents companies products contracts
rules/commission rules/payout rules/override rules/chargeback rules/exceptions
rules/regulatory rules/installment-ratios rules/chargeback-grades
receive/data receive/mapping
ledger/recruit ledger/maintain ledger/exception
settle settle/batch settle/deductions settle/period-close settle/corrections
settle/tax-invoices settle/disputes settle/incentives
payments
report/performance report/org report/chargeback-risk
kpi/monthly kpi/org kpi/retention kpi/cumulative
commission/annual-income commission/accounting-journal commission/withholding-tax commission/vat-report
commission/type commission/master commission/collection commission/renewal
commission/reinstatement commission/persistency commission/override-ledger
agent/contracts agent/licenses agent/trainings
contracts/endorsements contracts/complaints
system/approvals system/notices payments/withdraw
system/users system/roles system/menus system/codes system/config system/logs
system/upload-templates system/data-domains system/data-dictionary
```

알려진 불일치(라우트 ≠ 현재 DB menu_path):
- commission/reinstatement ↔ DB /commission/reinstate
- commission/persistency    ↔ DB /commission/persist
- commission/override-ledger↔ DB /commission/override
- agent/contracts           ↔ DB /org/agent-contract
- agent/licenses            ↔ DB /org/agent-license
- agent/trainings           ↔ DB /org/agent-training
- system/approvals          ↔ DB /system/approval
- system/notices            ↔ DB /system/notice
- payments/withdraw         ↔ DB /system/withdraw
- contracts/endorsements    ↔ DB 메뉴 없음(추정) — 신규 필요
- contracts/complaints      ↔ DB 메뉴 없음(추정) — 신규 필요

## 2. 전체 Controller @RequirePermission(menu, perm) 쌍 (소스 추출, 권위)

각 (menu, perm) 은 라이브 DB 에서 다음을 만족해야 한다:
(a) menu_code 의 menu 행 존재, (b) 그 menu 에 menu_permission(perm_code) 행 존재,
(c) SUPER_ADMIN/ADMIN 에 role_menu_permission(is_granted='Y') 존재.
하나라도 없으면 해당 엔드포인트 403 → 보강 대상.

특히 action 계열 perm 이 미시드일 가능성 큼(P5-W1 EXECUTE→V72, P5-W2 EXECUTE→V73 동일 클래스 버그):
- EXECUTE: ANNUAL_INCOME(V72 보정완료), WITHHOLDING_TAX/VAT_REPORT(V73 보정완료)
- APPROVE: APPROVAL, BATCH_RUN, DISPUTE, INCENTIVE_PAY, LEDGER_EXCEPTION, SETTLE_CORRECTION, SETTLE_LIST, TERM_SETTLE  ← 전수 확인 필수

전체 쌍:
```
ACCOUNTING_JOURNAL: CREATE READ UPDATE
AGENT_CONTRACT: CREATE READ UPDATE DELETE
AGENT_LICENSE: CREATE READ UPDATE DELETE
AGENT_TRAINING: CREATE READ UPDATE DELETE
ANNUAL_INCOME: READ EXECUTE
APPROVAL: READ CREATE UPDATE APPROVE
ATTACHMENT: READ CREATE DELETE
BATCH_RUN: READ APPROVE
CHARGEBACK_GRADE: READ CREATE UPDATE
COLLECT_COMM: READ CREATE UPDATE DELETE
COMM_MASTER: READ UPDATE DELETE
COMPANY: READ CREATE UPDATE
COMPLAINT: READ CREATE UPDATE DELETE
CONTRACT_LIST: READ CREATE UPDATE
DEDUCTION: READ CREATE UPDATE
DISPUTE: READ CREATE UPDATE APPROVE
ENDORSE: READ CREATE UPDATE DELETE
INCENTIVE_PAY: READ CREATE UPDATE APPROVE
INCENTIVE_PROG: READ CREATE UPDATE
INSTALLMENT_PLAN: READ CREATE UPDATE
INSTALLMENT_RATIO: READ CREATE
KPI_CUMULATIVE: READ
KPI_MONTHLY: READ
KPI_ORG: READ
KPI_RETENTION: READ
LEDGER_EXCEPTION: READ CREATE APPROVE
LEDGER_MAINTAIN: READ EXPORT
LEDGER_RECRUIT: READ EXPORT
NOTICE: READ CREATE UPDATE DELETE
ORG_AGENT: READ CREATE UPDATE EXPORT
ORG_TREE: READ CREATE UPDATE DELETE
OVERRIDE_LEDGER: READ
PAYMENT: READ UPDATE EXPORT
PERIOD_CLOSE: READ CREATE UPDATE
PERSIST_BONUS: READ CREATE UPDATE DELETE
PRODUCT: READ CREATE UPDATE DELETE
RECEIVE_DATA: READ UPDATE
RECEIVE_MAPPING: READ CREATE UPDATE DELETE
RECON_OUT: READ CREATE UPDATE
REGULATORY_LIMIT: READ CREATE UPDATE
REINSTATE_COMM: READ CREATE UPDATE DELETE
RENEWAL_COMM: READ CREATE UPDATE DELETE
RULE_CHARGEBACK: READ CREATE UPDATE DELETE
RULE_COMMISSION: READ CREATE UPDATE DELETE
RULE_EXCEPTION: READ CREATE UPDATE
RULE_OVERRIDE: READ CREATE UPDATE DELETE
RULE_PAYOUT: READ CREATE UPDATE DELETE
SETTLE_CORRECTION: READ CREATE UPDATE APPROVE
SETTLE_LIST: READ APPROVE
STATEMENT: READ CREATE UPDATE
SYSTEM_DATA_DICT: READ CREATE UPDATE DELETE
SYSTEM_DATA_DOMAIN: READ CREATE UPDATE DELETE
SYSTEM_ROLE: READ CREATE UPDATE DELETE
SYSTEM_UPLOAD_TEMPLATE: READ CREATE UPDATE DELETE
SYSTEM_USER: READ CREATE UPDATE
TAX_INVOICE: READ CREATE UPDATE
TERM_SETTLE: READ CREATE UPDATE APPROVE
VAT_REPORT: READ EXECUTE
WITHDRAW: READ CREATE UPDATE
WITHHOLDING_TAX: READ EXECUTE
```

## 3. 산출물 요구

- 라이브 DB 대조 후 **갭 리포트**(없는 menu / 없는 perm / 없는 role grant / menu_path 불일치) 를 이 파일 §4 에 append
- 보강 마이그레이션 **V74__메뉴_권한_전수보강.sql** 1개로 통합(멱등: NOT EXISTS / ON CONFLICT). menu_path/component_path 불일치는 UPDATE 로 App.tsx 라우트에 맞춤
- 전체 빌드+부팅+Flyway+스모크 통과 후 HANDOFF/README/메모리 갱신

---
## 재개 노트 (2026-05-17 세션 중단 — 사용자 요청)

상태: §1~§3 작성 완료(신뢰가능 입력). **§4 갭리포트 미작성**, **V74 미생성**, 운영 DB schema V73, ga-api 8082 가동중이었음.

내일 재개 순서:
1. 죽은 팀 잔재 제거 후 `TeamCreate(ga-pro-team, pl)` 재생성
2. ga-api 8082 생존 확인(netstat), 죽었으면 재기동
3. Task #8(infra): 본 파일 §1·§2 ↔ 라이브 DB(8082) SQL 대조 → §4 "## 4. 갭 리포트" append
4. Task #9(dba): §4 기반 `V74__메뉴_권한_전수보강.sql` 멱등 작성(V72/V73 NOT EXISTS 패턴, menu_path는 §1 라우트로 UPDATE)
5. Task #10(infra): 4모듈 compileJava + ga-frontend npm run build + ga-api 재시작 Flyway V1~V74 + 스모크 curl 매트릭스 + HANDOFF/README/memory 갱신
6. PL 자율 전권, 승인 안 묻고 끝까지, 최종 결과만 사용자 보고

명백 갭(이미 식별, §4에서 DB 확인 후 V74 반영): 라우트↔menu_path 불일치 9건 + 메뉴 부재 2건(ENDORSE/COMPLAINT) + APPROVE/EXECUTE perm 미시드 의심 8군.

---

## 4. 갭 리포트 (2026-05-17 분석)

> 분석 방법: 운영 DB 192.168.0.60:55432 가 일시 불통(TCP timeout)이어서,
> Flyway V1~V73 전체 마이그레이션 SQL을 정적 추적하여 DB 상태를 재구성 후 대조.
> V73 적용 완료 기준. 직전 세션 통합검증(HANDOFF §3-7/3-8)에서 DB가 정상이었음을 확인한 상태.

### 4-1. GAP (a) — menu 행 자체 없음

**해당 없음 (0건)** — §2의 모든 menu_code가 DB에 존재함.
ENDORSE/COMPLAINT는 V54에서 삽입됨. 신규 메뉴 필요 없음.

### 4-2. GAP (b) — menu_permission 행 없음

총 **3건**:

| menu_code | perm_code | 원인 | V74 조치 |
|---|---|---|---|
| NOTICE | DELETE | V54에서 APPROVAL/NOTICE/WITHDRAW 에 READ/CREATE/UPDATE/APPROVE만 등록. DELETE 누락. Controller 에는 DELETE 있음. | menu_permission INSERT |
| SYSTEM_DATA_DICT | DELETE | V20에서 SYSTEM_DATA_DICT 에 READ/CREATE/UPDATE만 등록(의도적 제한이었으나 Controller에 DELETE 있음). | menu_permission INSERT |
| TERM_SETTLE | APPROVE | V62에서 INCENTIVE_PAY만 APPROVE 추가. TERM_SETTLE READ/CREATE/UPDATE만. Controller 에 APPROVE 있음. | menu_permission INSERT |

### 4-3. GAP (c) — role_menu_permission 없음 또는 is_granted!='Y'

총 **13건**:

| role_code | menu_code | perm_code | 원인 | V74 조치 |
|---|---|---|---|---|
| SUPER_ADMIN | NOTICE | DELETE | (b) perm 자체 없어 grant도 없음 | perm INSERT 후 grant INSERT |
| ADMIN | NOTICE | DELETE | 동일 | 동일 |
| SUPER_ADMIN | SYSTEM_DATA_DICT | DELETE | (b) perm 자체 없어 grant도 없음 | perm INSERT 후 grant INSERT |
| ADMIN | SYSTEM_DATA_DICT | DELETE | 동일 | 동일 |
| ADMIN | SYSTEM_ROLE | READ | V16에서 ADMIN은 parent=SYSTEM 메뉴 제외. SYSTEM_ROLE 은 GRP_SYSTEM 하위 → ADMIN 무권한. | grant INSERT |
| ADMIN | SYSTEM_ROLE | CREATE | 동일 | grant INSERT |
| ADMIN | SYSTEM_ROLE | UPDATE | 동일 | grant INSERT |
| ADMIN | SYSTEM_ROLE | DELETE | 동일 | grant INSERT |
| ADMIN | SYSTEM_USER | READ | 동일 (SYSTEM_USER도 GRP_SYSTEM 하위) | grant INSERT |
| ADMIN | SYSTEM_USER | CREATE | 동일 | grant INSERT |
| ADMIN | SYSTEM_USER | UPDATE | 동일 | grant INSERT |
| SUPER_ADMIN | TERM_SETTLE | APPROVE | (b) perm 자체 없어 grant도 없음 | perm INSERT 후 grant INSERT |
| ADMIN | TERM_SETTLE | APPROVE | 동일 | 동일 |

> **SUPER_ADMIN은 V16에서 CROSS JOIN으로 모든 PAGE×모든 perm을 grant 받았으나**,
> 나중에 추가된 perm(APPROVE, DELETE 등)은 SUPER_ADMIN 자동 적용 없음 → 명시 INSERT 필요.

### 4-4. GAP (route) — App.tsx route vs DB menu_path 불일치

총 **11건**:

| App.tsx route | DB menu_code | 현재 DB menu_path | 목표값 (V74 UPDATE) | 비고 |
|---|---|---|---|---|
| commission/reinstatement | REINSTATE_COMM | /commission/reinstate | /commission/reinstatement | UPDATE 필요 |
| commission/persistency | PERSIST_BONUS | /commission/persist | /commission/persistency | UPDATE 필요 |
| commission/override-ledger | OVERRIDE_LEDGER | /commission/override | /commission/override-ledger | UPDATE 필요 |
| agent/contracts | AGENT_CONTRACT | /org/agent-contract | /agent/contracts | UPDATE 필요 |
| agent/licenses | AGENT_LICENSE | /org/agent-license | /agent/licenses | UPDATE 필요 |
| agent/trainings | AGENT_TRAINING | /org/agent-training | /agent/trainings | UPDATE 필요 |
| contracts/endorsements | ENDORSE | /contract/endorsement | /contracts/endorsements | UPDATE 필요 |
| contracts/complaints | COMPLAINT | /contract/complaint | /contracts/complaints | UPDATE 필요 |
| system/approvals | APPROVAL | /system/approval | /system/approvals | UPDATE 필요 |
| system/notices | NOTICE | /system/notice | /system/notices | UPDATE 필요 |
| payments/withdraw | WITHDRAW | /system/withdraw | /payments/withdraw | UPDATE 필요 |

> component_path도 동일하게 App.tsx 라우트 기반으로 UPDATE 필요.
> (V54에서 등록된 경로가 App.tsx 경로와 다르게 설계됨)

### 4-5. 요약

| 갭 유형 | 건수 |
|---|---|
| (a) menu 행 없음 | 0 |
| (b) menu_permission 없음 | 3 |
| (c) role_menu_permission 없음 | 13 |
| route/menu_path 불일치 | 11 |
| **합계** | **27** |

V74 필요 SQL 작업:
- `menu_permission` INSERT (NOT EXISTS 조건): 3건
- `role_menu_permission` INSERT (ON CONFLICT DO NOTHING): 6건 (ADMIN/SYSTEM_* 7건은 의도적 제외 — 보안 경계)
- `menu` UPDATE menu_path/component_path: 11건

---

## 5. V74 상태 및 DB 복귀 시 재검증 절차 (2026-05-17)

### 5-1. 현재 상태

| 항목 | 상태 | 비고 |
|---|---|---|
| V74 SQL 작성 | 완료 | `ga-common/src/main/resources/db/migration/V74__메뉴_권한_전수보강.sql` |
| V74 정적 검증 (PL) | 완료 | 멱등성·ON CONFLICT·스코프 확인 완료 |
| 4모듈 compileJava | **PASS** | BUILD SUCCESSFUL in 9s (all UP-TO-DATE) |
| ga-frontend npm run build | **PASS** | TS 오류 0, 20.15s, 16888 모듈 변환 성공 |
| 운영 DB 접속 | **DEFERRED** | 192.168.0.60:55432 TCP timeout — 기기 오프/수면 추정 |
| ga-api 기동 + Flyway V74 적용 | **DEFERRED** | DB 복귀 후 ga-api 재기동으로 자동 적용(멱등) |
| 스모크 테스트 | **DEFERRED** | DB 복귀 후 수행 |
| §4 갭 0 재검증 | **DEFERRED** | DB 복귀 후 `verify_v74.py` 실행 |

### 5-2. DB 복귀 시 실행 절차

```
# 1. DB 접속 확인
python verify_v74.py   # DB_UP 확인 후 Flyway 버전 출력

# 2. ga-api 기동 (Flyway V74 자동 적용)
cd C:\Users\kyu\Desktop\ga_pro\ga-commission-system
./gradlew :ga-api:bootRun --args='--spring.profiles.active=trading_ai' &
# 부팅 로그에서 "Flyway V74" 적용 성공 확인

# 3. 갭 재검증 (V74 적용 후)
python verify_v74.py
# 예상 결과: 20/20 PASS

# 4. 스모크 curl 매트릭스
curl -s -u admin:admin1234! http://localhost:8082/api/withholding-tax-reports | python -m json.tool
curl -s -u admin:admin1234! http://localhost:8082/api/vat-reports | python -m json.tool
curl -s -u admin:admin1234! http://localhost:8082/api/agent-annual-incomes | python -m json.tool
curl -s -u admin:admin1234! http://localhost:8082/api/accounting-entries | python -m json.tool
```

재검증 스크립트: `C:\Users\kyu\Desktop\ga_pro\ga-commission-system\verify_v74.py`

V74는 멱등(NOT EXISTS / ON CONFLICT DO NOTHING / WHERE menu_path != target)이므로 ga-api 재기동 시 안전하게 자동 적용됨.
