V13-FE-006: consolidate approved UI and contract hardening
deploy / deploy (push) Successful in 1m52s
deploy / notify (push) Successful in 1s

This commit is contained in:
2026-08-13 02:41:00 +09:00
parent d79edae546
commit 3f293d8aa8
1278 changed files with 14384 additions and 1664 deletions
+11 -1
View File
@@ -12,6 +12,7 @@ export interface NavigationEntry {
order: number
favoriteAllowed: boolean
internalOnly: boolean
permissions: readonly string[]
}
export interface NavigationSection {
@@ -23,6 +24,7 @@ function toEntry(route: NavigationRouteLike): NavigationEntry | null {
const meta = route.meta
if (!meta || typeof meta.screenId !== 'string' || typeof meta.module !== 'string') return null
if (meta.module === 'Home') return null
if (route.path.includes(':')) return null
return {
screenId: meta.screenId,
path: route.path,
@@ -31,10 +33,18 @@ function toEntry(route: NavigationRouteLike): NavigationEntry | null {
title: typeof meta.title === 'string' ? meta.title : route.path,
order: typeof meta.order === 'number' ? meta.order : 0,
favoriteAllowed: meta.favoriteAllowed !== false,
internalOnly: meta.internalOnly === true
internalOnly: meta.internalOnly === true,
permissions: Array.isArray(meta.permissions) && meta.permissions.every(permission => typeof permission === 'string')
? meta.permissions
: []
}
}
/** UI visibility hint only; the API remains the authorization authority. */
export function filterNavigationEntries(entries: readonly NavigationEntry[], grantedPermissions: ReadonlySet<string>): NavigationEntry[] {
return entries.filter(entry => entry.permissions.every(permission => grantedPermissions.has(permission)))
}
/** router.getRoutes()의 flat route 목록에서 즐겨찾기/검색/사이드바가 공유하는 단일 카탈로그를 파생한다. */
export function buildNavigationEntries(routes: readonly NavigationRouteLike[]): NavigationEntry[] {
const entries = routes.map(toEntry).filter((entry): entry is NavigationEntry => entry !== null)