# KBX Foundation v33
## Template State Matrix · Permission Host · Home Workbench Hardening

## 1. 배경

v32에서 T01~T09의 주요 Surface와 반복 조립 API를 표준화했지만, 다음 완성도 간극이 남아 있었다.

1. 조회형 화면의 최초 진입 상태가 실제 `0건 조회`와 구분되지 않았다.
2. `loading/empty/error/ready`는 존재했지만 Template별로 Dirty/Conflict/Validation/Job/Network까지 어떤 상태를 책임지는지 계약이 없었다.
3. `KbxCommandBar`, `KbxWorkflowBar`, `KbxBulkActionBar`에 permission callback은 있었지만 화면마다 전달해야 해서 누락 가능성이 있었다.
4. Home의 확인 필요 영역은 미저장/진행중/읽지 않음 총량 위주라 실패·부분완료·중요 알림 우선순위가 충분히 드러나지 않았다.
5. Navigation preference는 scope 분리와 safe route re-resolution은 있었지만 저장 payload 크기·문자열 길이·timestamp 검증·legacy migration 정규화가 더 필요했다.

v33은 이 다섯 지점을 해결하되 Domain Rule, Backend Permission, Server Validation을 UI framework로 끌어오지 않는다.

---

## 2. Template State Matrix

`KbxTemplateManifestEntry.stateCapabilities`를 추가했다.

| Template | 핵심 상태 책임 |
|---|---|
| T01 Search/List | idle, loading, refreshing, empty, error, permission |
| T02 Master CRUD | idle, loading, refreshing, empty, error, permission, dirty, conflict |
| T03 Transaction | loading, refreshing, error, permission, dirty, conflict, validation |
| T04 Fast Entry | loading, refreshing, error, permission, dirty, validation |
| T05 Master/Detail | idle, loading, refreshing, empty, error, permission |
| T06 Work Queue | idle, loading, refreshing, empty, error, permission |
| T07 Reconcile | idle, loading, refreshing, empty, error, permission |
| T08 Import | loading, refreshing, error, permission, validation, job |
| T09 WMS Mobile | loading, refreshing, error, permission, network |

핵심은 상태를 한 컴포넌트에 모두 몰아넣는 것이 아니라, **각 화면 유형이 책임져야 할 상태를 Manifest에서 검증 가능하게 만든 것**이다.

---

## 3. `idle` — 조회 전과 Empty 분리

`KbxAsyncState`에 `idle`을 추가했다.

기존 문제:

```text
화면 진입
→ 조회 API 미실행
→ rows = []
→ Empty처럼 보이거나 빈 Grid가 표시됨
```

v33:

```text
화면 진입
→ idle
→ [조회 F3]
→ loading
→ ready | empty | error
```

`KbxDataState`는 `조회 전입니다.`를 표시하고, `KbxTemplateStateBoundary`는 선택적인 `idleActionLabel` / `idleAction` 계약을 제공한다.

조회 중심 Template T01/T02(list 존재 시)/T05/T06/T07은 기본적으로 `조회 F3` 복구 Action을 연결한다.

실제 적용 화면:

- OMS 주문관리
- OMS 클레임
- ERP 품목관리
- ERP 재고현황
- UX Metrics
- WMS 작업 Queue

따라서 사용자는 “데이터가 없다”와 “아직 조회하지 않았다”를 구분할 수 있다.

---

## 4. Permission Host — 화면 내부 권한 누락 방지

새 내부 Host:

```text
KbxPermissionHostKey
```

Application Shell에서 현재 `grantedPermissions`를 Host로 제공한다.

자동 소비 Component:

- KbxScreenFrame
- KbxCommandBar
- KbxWorkflowBar
- KbxBulkActionBar
- KbxWmsMobilePage

명시적인 `can(permission)` prop이 있으면 prop을 우선하고, 없으면 Host를 사용한다.

효과:

```text
기존
Page가 can() 전달을 잊음
→ Command가 보일 수 있음
→ Backend에서 최종 거부

v33
Shell Permission Host
→ Screen/Command/Workflow/Bulk/WMS가 자동 동기화
→ Frontend에서 먼저 불필요한 Action 제거
→ Backend 최종 Enforcement 유지
```

이는 Backend 보안을 대체하지 않는다. UI 권한 표현의 누락 가능성을 줄이는 defense-in-depth다.

---

## 5. Screen-level Permission State

`KbxScreenFrame`과 `KbxWmsMobilePage`는 화면 자체 permission이 만족되지 않으면 업무 본문을 표시하지 않는다.

표현:

```text
이 화면을 사용할 권한이 없습니다.
현재 권한으로는 이 업무 화면을 열 수 없습니다.
```

DOM에는 `data-access="allowed|denied"`를 제공해 테스트/재현에서 상태를 식별할 수 있다.

App Shell의 route-level 권한 필터와 Backend Enforcement는 그대로 유지된다.

---

## 6. Home Actionable Attention

Home의 `확인 필요`를 다음 우선순위로 세분화했다.

1. 미저장 업무
2. 실패·부분완료 작업
3. Warning/Error 중요 알림
4. 진행 중 작업
5. 일반 새 알림

실패/중요 항목은 danger semantic token을 사용하되 텍스트를 함께 표시하므로 색상에만 의존하지 않는다.

Home Workbench의 기존 재개 우선순위는 유지한다.

```text
미저장 → 고정 → 열림 → 즐겨찾기 → 최근 → 권장
```

즉 Home은 Dashboard가 아니라 **현재 사용자가 다음에 처리해야 할 업무와 재개할 업무를 연결하는 Navigation Workbench**가 된다.

---

## 7. Navigation Preference v3 Hardening

저장 Key:

```text
kbx.navigation.preference.v3:{scope}
```

보강:

- 전체 payload 64KB 상한
- scope 최대 160자, 초과 시 저장 scope로 사용하지 않음
- ScreenId 최대 128자, 초과 데이터 거부
- Title 최대 120자, 표시용이므로 sanitize 후 truncate 허용
- Recent Path 최대 1024자, 초과 데이터 거부
- visitedAt parse 검증
- favorites 중복 제거/상한 유지
- recents 최신순 정렬/상한 유지

v3 데이터가 없으면 v2를 읽어 `normalizePreference()`를 통과시킨 뒤 v3로 자동 migration한다.

legacy raw object를 그대로 재사용하지 않는다.

---

## 8. Workspace URL Hardening

기존 차단:

- backslash
- encoded slash/backslash
- null/newline/tab encoding
- encoded `..`
- cross-origin
- route pattern mismatch

v33 추가:

- workspace candidate 최대 2048자
- raw ASCII control character 차단

Recent는 기존 정책대로 query/hash를 persistence/replay에서 제거한다.

---

## 9. 테스트/재현성

추가된 v33 Gate:

```text
scripts/validate-template-navigation-v33.mjs
```

검증 범위:

- idle async contract
- T01~T09 stateCapabilities
- idle action wiring
- Permission Host 제공/소비
- Golden/Reference idle 적용
- Home failed/urgent attention wiring
- Preference v3 bounds/migration
- Workspace URL length/control-character hardening
- Component SemVer/Catalog scenario

기존 `kbx-navigation-hardening.contract.spec.ts`의 Recent query/hash 기대값도 현재 정책에 맞게 수정하고, oversized/control-character path 테스트를 추가했다.

`kbx-template-state-matrix.contract.spec.ts`를 추가하여 Template별 상태 책임을 계약 테스트로 고정했다.

---

## 10. 기술부채 판단

이번 변경에서 피한 것:

- 모든 상태를 하나의 거대한 Dynamic State Engine으로 통합
- Permission을 UI에만 의존
- Home에 그래프/카드 Dashboard를 추가
- Notification/Operation payload 전체를 Home에 복제
- localStorage 암호화로 보안을 가장

대신 적용한 것:

- 작은 상태 Union + Template Manifest
- Vue provide/inject Permission Host
- 기존 Runtime Operation/Notification의 집계만 Home에 전달
- bounded preference normalization
- 기존 route capability resolver 재사용

결과적으로 UX 완성도는 올라가되 Domain/Backend 경계를 침범하지 않는다.
