import fs from 'node:fs';import path from 'node:path';import crypto from 'node:crypto'; import assert from 'node:assert/strict';import React from 'react';import {renderToStaticMarkup} from 'react-dom/server';import {createServer} from 'vite'; const candidate=fs.realpathSync(process.argv[2]||''); const app=fs.readFileSync(path.join(candidate,'resources/js/app.jsx'),'utf8'); const component=app.slice(app.indexOf('function AccessPanel('),app.indexOf("createRoot(document.getElementById('app'))")); assert(component.startsWith('function AccessPanel(')); const work=path.join('C:/laragon/data/sgf-tempo/run','admin-render-'+crypto.randomBytes(6).toString('hex')); fs.mkdirSync(work,{recursive:true});fs.symlinkSync(path.join(process.cwd(),'node_modules'),path.join(work,'node_modules'),'junction'); // Fixture-inject only the server response into the real candidate component. // Event handlers, permission filtering, labels and form markup are unchanged. const fixture=component.replace('function AccessPanel({ context, can, api, perform, busy })','export default function AccessPanel({ context, can, api, perform, busy, initialList, initialScope })') .replace('const [list, setList] = useState(null)','const [list, setList] = useState(initialList)') .replace("const [scope, setScope] = useState('company')","const [scope, setScope] = useState(initialScope)"); fs.writeFileSync(path.join(work,'AccessPanel.jsx'),"import React,{useState,useEffect} from 'react';\nconst labels={'unit.view':'Consultar unidade','company.view':'Consultar empresa'};\n"+fixture); const server=await createServer({root:work,configFile:false,server:{middlewareMode:true,fs:{allow:[work,process.cwd()]}},appType:'custom'}); const checks=[];const check=(value,name)=>{assert(value,name);checks.push(name);}; try{ const {default:Access}=await server.ssrLoadModule(path.join(work,'AccessPanel.jsx')); const unit=7,context={token:'synthetic',company:{id:3},unit:{id:unit},units:[{id:unit,name:'Unidade sintética'}]}; const rights=['unit.view','unit.edit','purchasing_requisitions.view','purchasing_requisitions.prepare','purchasing_requisitions.approve.department_head','purchasing_budget.create','purchasing_budget.approve']; const list={members:[{id:1,name:'Sintético',email:'example@example.test'}],grants:[{id:1,user_id:1,permission:'purchasing_requisitions.prepare',unit_id:unit}],catalogue:{company:['company.view','access.manage'],unit:rights},catalogue_labels:{'purchasing_requisitions.prepare':'Preparar e submeter requisições','purchasing_requisitions.approve.department_head':'Aprovar como responsável de departamento','purchasing_budget.create':'Preparar dotações','purchasing_budget.approve':'Aprovar dotações'}}; const render=(granted,initialList=list,initialScope=String(unit))=>renderToStaticMarkup(React.createElement(Access,{context,initialList,initialScope,can:(p,u=null)=>granted.some(g=>g[0]===p&&g[1]===u),api:async()=>{},perform(){},busy:false})); const preparer=render([['unit.view',unit],['purchasing_requisitions.prepare',unit],['purchasing_budget.create',unit]]); check(preparer.includes('value="purchasing_requisitions.prepare"'),'native selector offers server catalogue requisition right'); check(preparer.includes('Preparar e submeter requisições'),'native selector uses server labels'); check(preparer.includes('Preparar dotações'),'budget creation right has server label'); check(!preparer.includes('value="purchasing_budget.approve"'),'preparer cannot delegate budget approval'); check(!preparer.includes('value="purchasing_requisitions.approve.department_head"'),'preparer cannot delegate absent decision authority'); const reviewer=render([['unit.view',unit],['purchasing_budget.approve',unit]]); check(reviewer.includes('value="purchasing_budget.approve"'),'reviewer sees only own approval grant'); check(!reviewer.includes('value="purchasing_budget.create"'),'reviewer cannot delegate preparation'); const foreign=render([['purchasing_requisitions.prepare',99]]); check(!foreign.includes('value="purchasing_requisitions.prepare"'),'foreign unit grant never becomes a local option'); const reduced=render([['purchasing_requisitions.prepare',unit]],{...list,catalogue:{company:[],unit:['unit.view']}}); check(!reduced.includes('value="purchasing_requisitions.prepare"'),'client cannot invent a catalogue entry from a grant'); const waiting=render([['purchasing_requisitions.prepare',unit]],null); check(!waiting.includes('value="purchasing_requisitions.prepare"'),'no hardcoded new rights before server catalogue loads'); check(preparer.includes('