Files
KArtSell.Aegis/docs/Design/kbx-foundation-v36/scripts/validate-template-navigation-v28.mjs
T

22 lines
3.0 KiB
JavaScript

import fs from 'node:fs'
import path from 'node:path'
const root=process.cwd();const fail=[];const read=p=>fs.readFileSync(path.join(root,p),'utf8')
const manifest=read('packages/kbx-ui/src/registry/templateManifest.ts')
for(const code of ['T01','T02','T03','T04','T05','T06','T07','T08','T09'])if(!manifest.includes(`code:'${code}'`))fail.push(`template manifest missing ${code}`)
for(const type of ['list','master','transaction','fast-entry','master-detail','queue','reconcile','import','wms-mobile'])if(!manifest.includes(`type:'${type}'`))fail.push(`template manifest missing type ${type}`)
for(const file of ['KbxListPage.vue','KbxMasterPage.vue','KbxTransactionPage.vue','KbxFastEntryPage.vue','KbxMasterDetailPage.vue','KbxQueuePage.vue','KbxReconcilePage.vue','KbxImportPage.vue']){
const text=read(`packages/kbx-ui/src/components/${file}`)
if(!text.includes('KbxTemplateContextBar'))fail.push(`${file} missing shared template context surface`)
}
const reconcile=read('packages/kbx-ui/src/components/KbxReconcilePage.vue');for(const x of ['name="resolution"','name="audit"','name="detail"'])if(!reconcile.includes(x))fail.push(`T07 missing ${x}`)
const imp=read('packages/kbx-ui/src/components/KbxImportPage.vue');if(!imp.includes('name="result"'))fail.push('T08 missing result surface')
const wms=read('packages/kbx-ui/src/wms/KbxWmsMobilePage.vue');for(const x of ['taskContext','instruction','name="context"','name="actions"'])if(!wms.includes(x))fail.push(`T09 missing ${x}`)
const home=read('packages/kbx-ui/src/shell/KbxHomePage.vue');for(const x of ['이어서 작업','resumeTab','selectedModule','모듈별 업무'])if(!home.includes(x))fail.push(`Home missing ${x}`)
const side=read('packages/kbx-ui/src/shell/KbxSideNavigation.vue');for(const x of ['module-switcher','menuSearch','selectedModule','최근메뉴'])if(!side.includes(x))fail.push(`Side navigation missing ${x}`)
const search=read('packages/kbx-ui/src/shell/KbxMenuSearch.vue');if(!search.includes('priorityScreenIds'))fail.push('Menu search missing favorite/recent priority')
const store=read('apps/web/src/shell/workspaceStore.ts');for(const x of ['setPreferenceScope','STORAGE_PREFIX','normalizePreference','encodeURIComponent','if(scopeKey.value','syncRoute(screenId:string,title:string,path:string,recent?:'])if(!store.includes(x))fail.push(`Preference security missing ${x}`)
const frame=read('apps/web/src/shell/KbxAppFrame.vue');for(const x of ['preferenceScope','recentPolicy','navEntry.path','setPreferenceScope','item.path.startsWith(nav.path)','allowedTabs'])if(!frame.includes(x))fail.push(`App frame missing secure navigation contract ${x}`)
const tabs=read('packages/kbx-ui/src/shell/KbxWorkspaceTabs.vue');for(const x of ["role=\"tablist\"","ArrowLeft","ArrowRight","Delete",':max-tabs']){if(x===':max-tabs')continue;if(!tabs.includes(x))fail.push(`Workspace tabs missing ${x}`)}
if(fail.length){console.error(fail.join('\n'));process.exit(1)}
console.log('v28 template/navigation hardening validation passed for T01-T09, Home, secure preferences, menu search, and workspace tabs.')