# KBX v29 Template & Home Navigation Completion

## 1. 목적

v29은 화면 수를 늘리는 작업이 아니다.

목표는 다음 두 가지다.

1. **T01~T09 Template을 선택하면 Loading/Empty/Error/Refreshing, Utility, Density, Accessibility까지 기본 UX가 결정되는 상태**
2. **Home/Shell이 업무 시작·복귀·전환·개인화를 맡되 Tenant/User/Permission 변경에 안전한 상태**

KBX가 정의한 `Vertical Slice는 업무를 구현하고, KBX는 UX를 구현한다`는 경계를 Template과 Application Shell 수준에서 더 강하게 만든다.

---

## 2. Template Manifest 완성 계약

`kbxTemplateManifest`의 모든 T01~T09 항목은 다음 메타데이터를 가진다.

```text
code
screen type
template component
purpose
required surfaces
optional surfaces
keyboard
reference screens
default density
runtime states
utility surfaces
accessibility
```

이 정보는 문서용 목록이 아니라 Scaffolder, AI Coding Grounding, Governance Gate가 공유하는 계약이다.

### Density

```text
T01~T08 → compact
T09     → touch
```

Desktop 업무를 Consumer UI처럼 과도하게 여유롭게 만들지 않고, WMS Mobile은 48px+ Touch Target 원칙을 분리한다.

---

## 3. Runtime State Boundary

신규 `KbxTemplateStateBoundary`가 Template의 비동기 상태를 통일한다.

```text
Loading
Empty
Error
Ready
Refreshing
```

### 최초 Loading

Content 대신 명시적 `조회 중...` 상태를 제공한다.

### Empty

업무에 맞는 빈 결과 설명과 필요 시 복구 Action을 제공한다.

### Error

오류를 Toast로 흘려보내지 않고 해결 가능한 위치에 고정하고 `다시 조회/재시도`를 제공한다.

### Refreshing

기존 Grid/Form/선택 Context를 제거하지 않는다.

```text
기존 화면 유지
+ 최신 내용을 조회 중입니다.
```

이는 조회 중 사용자가 화면 Context를 잃지 않도록 하는 표준을 Template 기본 동작으로 승격한 것이다.

---

## 4. T01~T09 적용

### T01 Search/List

`KbxListPage` content가 Runtime Boundary 안에서 동작하며 retry는 조회 Command로 돌아간다.

### T02 Master CRUD

Master/Detail body 전체에 Boundary를 적용해 목록 조회 오류와 상세 Context가 임의로 분리되지 않는다.

### T03 Transaction

Header/Detail/Workflow/Summary/Audit 영역을 하나의 Transaction Context로 유지하면서 reload recovery를 제공한다.

### T04 Fast Entry

Paste/Fill Down/행 편집 상태를 유지한 채 재조회/오류 복구가 가능하다.

### T05 Master/Detail

Master 선택과 Detail/History Context가 재조회 중 사라지지 않는다.

### T06 Work Queue

Queue와 Exception Context를 같은 Runtime State에서 관리한다.

### T07 Reconcile

Comparison/Resolution/Audit Context를 유지한 상태로 오류 복구한다.

### T08 Import

Import 진행/결과를 Template Boundary와 연결한다.

### T09 WMS Mobile

현장 Content도 동일한 State 계약을 사용하되 Touch/Network/Instruction Context는 유지한다.

---

## 5. Global Screen Utility Host

기존에는 Help/AI/제안을 화면마다 연결해야 했다.

v29은 Shell이 `KbxScreenUtilityHost`를 제공하고 Template의 `KbxScreenFrame`이 현재 Screen Definition을 기준으로 사용 가능한 Utility를 자동 노출한다.

```text
Screen Definition
     ↓
Utility Host
     ├─ Help Registry
     ├─ AI Capability
     └─ Suggestion Permission
     ↓
Page Header
[도움말] [AI] [제안]
```

AI는 현재 사용자의 effective capability 범위 안에서만 열린다.

사용자 제안은 `common.suggestion.create` permission이 있을 때만 제공한다.

화면이 특수 Utility slot을 명시하면 기본 Utility를 중복 표시하지 않는다.

WMS T09은 현장 집중도 때문에 Help를 기본 보조 기능으로 제한한다.

---

## 6. Home을 업무 시작 Hub로 강화

Home은 카드 Dashboard가 아니다.

v29 정보 우선순위는 다음과 같다.

```text
메뉴/화면 검색
↓
확인 필요 + 미저장 업무
↓
주요 업무 Quick Start
↓
이어서 작업
↓
즐겨찾기 / 최근 업무
↓
모듈별 업무
```

### 주요 업무 Quick Start

`buildKbxHomeQuickStart()`가 다음 순서로 후보를 결합한다.

```text
Favorites
→ Open Workspace Tabs
→ Recent Screens
→ Navigation homePriority
```

같은 Screen은 ScreenId 기준으로 한 번만 노출한다.

Home.vue에 이 정책을 직접 흩어 놓지 않고 순수 함수로 분리해 단위 테스트할 수 있게 했다.

---

## 7. Tenant/User Scope 격리

v28은 localStorage key를 scope별로 나눴다.

v29은 한 단계 더 나아가 **메모리 Workspace 자체도 scope에 종속**시킨다.

```text
Scope A
 ├ tabs
 ├ active tab
 ├ menu search state
 └ utility/runtime state

Scope A → Scope B
 ↓
A의 in-memory workspace 폐기
 ↓
Home 복귀
 ↓
B preference load
```

이전 사용자의 열린 주문/품목 제목이나 동적 Route가 다음 사용자에게 노출되지 않는다.

---

## 8. Permission 변경 시 열린 업무 정리

권한은 로그인 시점에만 고정된다고 가정하지 않는다.

현재 Permission Set이 바뀌면:

```text
현재 허용 ScreenId 재계산
↓
허용되지 않은 Workspace Tab prune
↓
active tab 재결정
↓
Utility/Runtime Panel close
```

Frontend는 정보 노출과 UX 일관성을 위한 방어선이며 최종 보안은 Backend Permission/Domain이 책임진다.

---

## 9. Workspace 최대 Tab 실제 강제

기존 `workspaceMaxTabs`가 표시/Preference 수준이었다면 v29은 실제 open policy로 사용한다.

허용 범위:

```text
8 ~ 12
```

최대치에서 새 업무를 열면:

```text
clean
+ unpinned
+ inactive
```

Tab 중 LRU 하나만 자동 정리한다.

다음은 자동 제거하지 않는다.

- Dirty Tab
- Pinned Tab
- Active Tab

정리할 수 없다면 새 Tab을 열지 않고 Shell Notice로 사용자가 다음 행동을 결정하게 한다.

---

## 10. Persisted Recent는 신뢰 입력이 아니다

localStorage의 path는 사용자가 수정할 수 있다.

`resolveKbxSafeRecentPath()`는 다음을 확인한다.

```text
현재 ScreenId가 허용 Catalog에 존재
same origin
catalog base pathname과 exact/prefix boundary 일치
현재 Permission 통과
```

예:

```text
base: /oms/orders
allowed: /oms/orders/123/edit
blocked: /oms/orders-evil
blocked: https://external.example/...
```

검증에 실패하면 dynamic saved path를 버리고 canonical catalog path로 돌아간다.

---

## 11. Menu Search 접근성

`KbxMenuSearch`는 단순 overlay가 아니라 keyboard-accessible application search로 정리했다.

```text
role=dialog
input role=combobox
results role=listbox
item role=option
aria-activedescendant
focus trap
ArrowUp/ArrowDown
Enter
Esc
```

Mouse 없이 메뉴검색 → 결과 선택 → 화면 이동까지 완료할 수 있다.

---

## 12. Design Token / 기술부채

신규 Shell/Template 치수는 CSS literal로 남기지 않고 canonical token으로 승격했다.

추가 영역:

- Template refresh state
- Home quick-start row
- Home module label
- Shell notice
- Utility panel width
- Visually hidden accessibility size

최종 Token 수는 134다.

Design debt는 v28 305에서 v29 294로 감소했으며, v29 결과를 다음 ratchet baseline으로 사용한다.

---

## 13. 완료 판단

v29의 핵심 완료 기준은 다음이다.

```text
새 화면 생성
→ T01~T09 선택
→ 기본 Layout 결정
→ Runtime State 결정
→ Utility 결정
→ Density 결정
→ Keyboard/A11y 결정
→ 업무 Slice는 Domain 데이터·Command·Exception만 연결
```

Home은:

```text
로그인/Context 확정
→ 안전한 개인화 load
→ 주요 업무 진입
→ 열린 업무 재개
→ 권한/Scope 변경 시 안전하게 정리
```

까지 책임진다.
