/* Same proof core in a dedicated realm; no untrusted URL, eval or private-key persistence. */
(function(){
  'use strict';
  const node=typeof process!=='undefined'&&!!process.versions?.node;
  let K,send,receive,load;
  if(node){
    const {parentPort}=require('node:worker_threads');const fs=require('node:fs'),path=require('node:path');
    K=require('./доказательный-контур.js');send=(m,transfer=[])=>parentPort.postMessage(m,transfer);receive=fn=>parentPort.on('message',fn);
    load=async()=>{const root=path.resolve(__dirname,'../..'),profile=JSON.parse(fs.readFileSync(path.join(root,'данные/профиль-схем-4.8.0.json')));const out={};for(const [k,url]of Object.entries(profile.файлы))out[k]=JSON.parse(fs.readFileSync(path.join(root,url.replace(/^\//,''))));K.configureSchemas(out);return JSON.parse(fs.readFileSync(path.join(root,'данные/схема-оценки-когнитивной-свободы-4.8.0.json')));};
  }else{
    importScripts('доказательный-контур.js?редакция=4.8.0-wip');K=globalThis.ВойнаМетодика;send=(m,transfer=[])=>postMessage(m,transfer);receive=fn=>{onmessage=e=>fn(e.data);};
    load=async()=>{const get=async url=>{const r=await fetch(new URL('../../'+url.replace(/^\//,''),location.href),{cache:'no-store',credentials:'same-origin'});if(!r.ok)throw Error('Схема рабочего потока не загружена: '+r.status);return r.json();};const profile=await get('данные/профиль-схем-4.8.0.json'),out={};for(const [k,url]of Object.entries(profile.файлы))out[k]=await get(url);K.configureSchemas(out);return get('данные/схема-оценки-когнитивной-свободы-4.8.0.json');};
  }
  if(K.RELEASE!=='4.8.0-wip')throw Error('Редакция ядра рабочего потока не совпадает с редакцией диспетчера.');
  let busy=false;
  receive(async message=>{
    if(busy)return;busy=true;
    const {id,command,data,protocol}=message||{};
    const stage=name=>send({id,type:'stage',stage:typeof name==='string'?name:name.этап});
    try{
      if(protocol!=='война/поток/1'||!Number.isSafeInteger(id))throw Error('Неверный протокол рабочего потока.');
      K.resourceCheck(data,{envelope:true});stage('снимок принят');
      const schema=await load(),options={onStage:stage};stage('схемы загружены');
      let value;
      switch(command){
        case 'canonical':value=K.canonical(data);break;
        case 'seal':value=await K.seal(data,options);break;
        case 'case-import':value=await K.importCaseBytes(await data.file.arrayBuffer(),data.file.name||'дело.json',options);break;
        case 'case-export':value=await K.exportCase(data,options);break;
        case 'case-transfer':case 'panel-transfer':{const record=command==='case-transfer'?await K.exportCase(data,options):await K.seal(data,options);stage('перед сериализацией');const bytes=K.canonicalBytes(record);value={record,bytes:bytes.buffer};stage('сериализация завершена');break;}
        case 'case-explanation':{const errors=await K.caseErrors(data,options);if(errors.length)throw Error(errors.join('\n'));value=await K.seal({...K.correctionExplanation(data),отпечаток_папки:await K.hashCanonical(K.payload(data))},options);break;}
        case 'registry-history':value=await K.registryHistory(data,options);break;
        case 'registry-link':value=await K.recoverRegistryLink(data.migration,data.index,options);break;
        case 'receipt':{
          K.resourceCheck([data.receipt,data.request,data.response],{files:true});
          const raw=await data.receipt.arrayBuffer();stage('квитанция прочитана');
          const receipt=K.parse(new TextDecoder('utf-8',{fatal:true}).decode(raw));
          const checked=await K.verifyCallReceipt(receipt,await data.request.arrayBuffer(),await data.response.arrayBuffer(),{...options,pinnedKey:data.pin||null});
          value={редакция:K.RELEASE,вид:'локальная проверка квитанции',исходная_квитанция:K.base64(new Uint8Array(raw)),отпечаток_квитанции:await K.hash(raw),заявленный_источник_закрепления:data.pinSource||'',публикация_ключа:'не проверена',период_и_отзыв_ключа:'не установлены',результат:checked,счётчик_повторов:'не изменён',граница:'Исходные байты запроса и ответа не включены в экспорт. Источник закрепления — текст пользователя, не удостоверенная публикация.'};break;
        }
        case 'panel-import':{
          K.resourceCheck(data.files,{files:true,envelope:!!data.restore});
          let pending=[],decisions=[...data.decisions],revocations=[...data.revocations],migrations=[...data.migrations];
          // Re-ingestion establishes private trust in this realm. A transferred marker never does.
          for(const old of data.sources){const s=await K.ingest(K.unbase64(old.база64),old.имя,schema);if(s.отпечаток_исходного_файла!==old.отпечаток_исходного_файла)throw Error('Прежний источник не совпал с исходными байтами.');pending.push(s);}
          const add=(target,extra,key)=>{for(const x of extra){const old=target.find(y=>y[key]===x[key]);if(old&&K.canonical(old)!==K.canonical(x))throw Error('Конфликт истории: '+key);if(!old)target.push(x);}};
          for(const [fileIndex,f] of data.files.entries()){stage('чтение исходника');
            if(data.restore){const restored=await K.importPanelBytes(await f.arrayBuffer(),data.names?.[fileIndex]||f.name||'панель.json',schema,options);pending.push(...restored);add(decisions,restored.разрешения||[],'идентификатор');add(revocations,restored.отзывы||[],'идентификатор');add(migrations,restored.переносы||[],'отпечаток_файла');}
            else pending.push(await K.ingest(await f.arrayBuffer(),data.names?.[fileIndex]||f.name||'исходник.json',schema));
          }
          pending=(await K.mergeAsync(pending,schema,[],[],[],options)).источники;
          if(pending.length>K.INTERACTIVE_PROFILE.files||pending.reduce((n,s)=>n+s.байты,0)>K.INTERACTIVE_PROFILE.totalFileBytes)throw Error('Ограничительный профиль: объединённый состав превышает 25 исходников или 8 МиБ.');
          value=await K.mergeAsync(pending,schema,decisions,revocations,migrations,options);break;
        }
        default:throw Error('Неизвестная операция рабочего потока.');
      }
      stage('результат вычислен');K.resourceCheck(value,{envelope:true});
      send({id,type:'result',value},value?.bytes instanceof ArrayBuffer?[value.bytes]:[]);
    }catch(e){send({id,type:'error',name:e.name||'Error',message:String(e.message||e)});}
  });
})();
