/** * cli:derive-permission-floor — menu-nodes.ts * * Menu-tree readers: the floor derives from the FOLDER TREE (Application → * Module → Section → Resource, each node a folder holding index.md), the same * source scaffold-core-seed's Phase 0 seeds from. Folder → nav code follows * the create-rbac normalization: lowercase, `UPPERCASE_SNAKE` → kebab. */ import { readdirSync } from 'node:fs' import { join } from 'node:path' import { listSections } from '../derive-lookup-grants/rbac-rows.js' export { listSections } /** `HR_PORTAL` → `hr-portal` — the create-rbac path normalization. */ export function navCodeOf(folder: string): string { return folder.toLowerCase().replace(/_/g, '-') } /** * Resource folders of a section — lower-kebab directories under * `///
/` (same filter as listSections: * `_`/`.` prefixes are workflow folders). */ export function listResources( baRoot: string, app: string, module: string, section: string, ): string[] { const sectionDir = join(baRoot, app, module, section) let entries try { entries = readdirSync(sectionDir, { withFileTypes: true }) } catch { return [] } return entries .filter( (e) => e.isDirectory() && !e.name.startsWith('_') && !e.name.startsWith('.') && /^[a-z]/.test(e.name), ) .map((e) => e.name) .sort() }