# KBX v30 Template · Component · Home Navigation Hardening

## 1. 목적

v30의 목표는 Component 수를 늘리는 것이 아니다. 신규 업무 화면이 만들어질 때 **표준 Template 선택만으로 배치·상태·입력·탐색·복구의 기본 품질이 재현**되도록 하는 것이다.

기준은 다음이다.

```text
화면 유형 선택
→ 핵심 Component 결정
→ 필수 Surface 생성
→ Runtime/Utility/A11y 계약 적용
→ 업무 Rule 연결
→ CI에서 표준 누락 차단
```

## 2. T01~T09 Manifest를 완료 기준으로 확장

각 Template는 기존 `requiredSurfaces`, `optionalSurfaces`, `keyboard`, `runtimeStates` 외에 다음을 갖는다.

- `coreComponents`: 해당 유형에서 우선 사용하는 KBX Business Component
- `completionChecks`: 화면 리뷰와 AI Code Generation이 반드시 확인할 체크리스트

예를 들어 T03 Transaction은 `KbxFormSection + KbxFormGrid + KbxDataGrid + KbxSummaryBar + KbxRecordLifecycle`을 중심으로 Header 2-column, Header→Detail Focus, Dirty 상태의 위험 Workflow 차단, 서버 재검증, Optimistic Concurrency 복구를 확인한다.

## 3. 신규 화면 생성기 회귀 차단

기존 Scaffolder에는 오래된 mapping이 남아 있었다.

```text
fast-entry → KbxTransactionPage   (잘못됨)
queue      → KbxWorkQueuePage     (호환 Wrapper)
```

v30은 이를 canonical mapping으로 수정했다.

```text
list          → KbxListPage
master        → KbxMasterPage
transaction   → KbxTransactionPage
fast-entry    → KbxFastEntryPage
master-detail → KbxMasterDetailPage
queue         → KbxQueuePage
reconcile     → KbxReconcilePage
import        → KbxImportPage
wms-mobile    → KbxWmsMobilePage
```

`validate-scaffolder.mjs`는 9개 유형을 모두 임시 생성하고 Template, required surface, PrimeVue/AG Grid 직접 노출 여부, Help stub까지 확인한다.

## 4. Desktop Form Composition

`KbxFormSection`이 Section과 Grid Layout을 동시에 담당하지 않도록 SRP를 정리했다.

```text
KbxFormSection
  └ Section title / description / action

KbxFormGrid
  └ Desktop 기본 2-column
  └ 좁은 화면 1-column

KbxFormSpan
  └ cell | full
```

현재 품목관리, 주문등록, 구매등록, 재고이동에 적용했다. 주소처럼 서로 관계가 있고 긴 입력은 `full`로 배치한다. Label은 기존 Field Component의 canonical `--kbx-label-width`를 계속 사용한다.

## 5. Home을 하나의 Workbench로 정리

v29의 주요 업무/이어서 작업/즐겨찾기/최근업무는 의미가 겹칠 수 있었다. v30은 `buildKbxHomeWorkbench()`로 다음 우선순위를 하나의 목록으로 만든다.

```text
미저장 업무
→ 열린 업무
→ 즐겨찾기
→ 최근 업무
→ Home Priority
```

같은 ScreenId는 한 번만 노출한다. 각 행에는 `미저장 / 열림 / 즐겨찾기 / 최근 / 권장` 출처를 명시한다. 전체 탐색은 별도의 `모듈별 업무`에서 담당한다.

## 6. Global Module Navigation

Reference Shell의 `[OMS ▼]` 문법을 실제 동작으로 승격했다. `KbxGlobalHeader`의 Module Selector와 Side Navigation의 선택 모듈은 `KbxApplicationShell.focusedModule`을 공유한다.

```text
Header에서 ERP 선택
→ Side Navigation도 ERP Context

Side Navigation에서 WMS 선택
→ Header Selector도 WMS
```

현재 열려 있는 Screen의 module이 바뀌면 focused module도 다시 동기화된다.

## 7. Route Capability와 Deep-link 복구

Workspace/Recent에 저장된 문자열은 Navigation 권한으로 간주하지 않는다. Router의 실제 Screen Definition으로 `screenRoutePatterns`를 생성하고, 이동 직전에 다음을 확인한다.

```text
현재 ScreenId Permission
+ same-origin
+ 해당 ScreenId에 등록된 route pattern
```

`:orderId`, `:taskId` 같은 동적 segment는 등록된 위치에서만 허용한다. 검증되지 않은 path는 Home/canonical route로 fallback한다.

등록되지 않은 URL은 catch-all `KbxRouteNotFound`로 이동하여 빈 화면 대신 `메뉴 검색`과 `홈으로 이동` 복구 Action을 제공한다.

## 8. Access Denied 정보 노출 최소화

`KbxAccessDenied`는 기본 `revealDetails=false`다. 따라서 권한 없는 사용자가 직접 URL을 추측해도 Screen Title과 ScreenId를 기본 노출하지 않는다. 업무상 기능 존재를 알려야 하는 정책에서만 명시적으로 상세정보를 허용할 수 있다.

이것은 Frontend 정보노출 방어이며 실제 데이터/API 권한은 Backend가 최종 Enforcement한다.

## 9. Dead Action 제거

Global Header의 `사용자` 버튼은 v29에서 emit이 Shell Host까지 전달되지 않아 통합 환경에 따라 dead action이 될 수 있었다. v30은 `GlobalHeader → ApplicationShell → KbxAppFrame → Host`로 `profile` action을 전파한다.

## 10. Design Token / 기술부채

Form Section/Grid, Home Workbench, Global Header Module Selector 관련 치수를 canonical token으로 승격했다.

```text
v29 debt 294
v30 debt 286
```

신규 코드가 기존 ratchet을 증가시키지 않으며 v30의 286을 다음 baseline으로 사용한다.

## 11. 완료 판단

v30 이후 신규 화면은 “어떤 Component를 배치할까?”보다 다음을 먼저 판단해야 한다.

- 어떤 T01~T09 유형인가?
- Manifest completion check를 충족하는가?
- Form은 표준 composition을 쓰는가?
- Home/Navigation에 중복 진입점을 만들고 있지 않은가?
- persisted path/permission을 다시 검증하는가?
- 잘못된 접근에서 사용자가 안전하게 복구할 수 있는가?
