# 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 경계를 침범하지 않는다.