import {PGlite} from '@electric-sql/pglite';
export const policy=`CREATE ROLE lab_reader NOLOGIN NOSUPERUSER NOBYPASSRLS;
GRANT USAGE ON SCHEMA public TO lab_reader;
GRANT SELECT,UPDATE ON documents TO lab_reader;
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
ALTER TABLE documents FORCE ROW LEVEL SECURITY;
CREATE POLICY tenant_access ON documents TO lab_reader
USING (tenant_id = current_setting('app.tenant',true))
WITH CHECK (tenant_id = current_setting('app.tenant',true));`;
export function authorize(session,action,now){
 if(!session||session.expires<=now)return {allowed:false,status:401,reason:'The fixture session has expired.'};
 if(!session.memberships.includes(session.tenant))return {allowed:false,status:403,reason:'The verified account is not a member of the selected company.'};
 if(action==='update'&&session.role!=='editor')return {allowed:false,status:403,reason:'A viewer can read this company’s documents but cannot edit them.'};
 return {allowed:true,status:200,reason:'The verified session establishes company membership and the requested action.'};
}
export async function runTenant(config,options={}){
 const presets=['cross-tenant','viewer-edit','expired','missing-filter'];if(!presets.includes(config.preset))throw new Error('Choose a listed authorization scenario.');
 const safe=config.variant==='safe',now=2000,session={tenant:'orchard',memberships:['orchard'],role:config.preset==='viewer-edit'?'viewer':'editor',expires:config.preset==='expired'?1999:3000};
 const action=config.preset==='viewer-edit'?'update':'read';
 const db=new PGlite(options);try{
  await db.exec(`CREATE TABLE documents(id int PRIMARY KEY,tenant_id text NOT NULL,title text NOT NULL);INSERT INTO documents VALUES(11,'orchard','Orchard budget'),(22,'harbor','Harbor payroll');`);
  const verdict=safe?authorize(session,action,now):{allowed:true,status:200,reason:'Broken handler checks only that a session object exists.'};
  const trace=[verdict.reason];let rows=[],code='',status=verdict.status;
  if(verdict.allowed){
   if(safe){await db.exec(policy);await db.exec('SET ROLE lab_reader');await db.query("SELECT set_config('app.tenant',$1,false)",[session.tenant]);trace.push('The handler selects the restricted database role and derives the tenant from the verified session, never the request body.');}
   const target=config.preset==='cross-tenant'?22:11;
   if(action==='update'){code='UPDATE documents SET title=$1 WHERE id=$2 RETURNING id,tenant_id,title';rows=(await db.query(code,['Changed by viewer',target])).rows;}
   else if(config.preset==='missing-filter'){code='SELECT id,tenant_id,title FROM documents ORDER BY id';rows=(await db.query(code)).rows;}
   else{code='SELECT id,tenant_id,title FROM documents WHERE id=$1';rows=(await db.query(code,[target])).rows;}
   if(!rows.length){status=404;trace.push('The database returned no visible row. The API uses the same missing-record response for absent and inaccessible identifiers.');}
   if(safe)trace.push('PostgreSQL applied the tenant policy even when the SELECT omitted a tenant WHERE clause. Table owners and privileged roles require separate care.');
  }else{code='Denied before the data query.';trace.push('No SELECT or UPDATE was executed for this request.');}
  return {title:safe?'Enforce the boundary at each layer':'A session alone is not permission',summary:'These are invented sessions and real PostgreSQL row policies. All records live in your browser; the public example is not a login service.',metrics:[['Response status',status],['Rows returned',rows.length],['Foreign rows',rows.filter(r=>r.tenant_id!=='orchard').length]],trace,tables:[{title:'Rows visible to this request',columns:['ID','Company','Title'],rows:rows.map(r=>[r.id,r.tenant_id,r.title])},{title:'Session fixture',columns:['Field','Value'],rows:Object.entries(session).map(([k,v])=>[k,JSON.stringify(v)])}],code:safe?policy+'\n\n'+code:code};
 }finally{await db.close();}
}
