import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import crypto from 'node:crypto'; import {fileURLToPath} from 'node:url'; import {issue} from '../scripts/enterprise-auth/issue.mjs'; import {exportRecipient} from '../scripts/enterprise-auth/export-recipient.mjs'; import {install,validateDelivery} from '../scripts/enterprise-auth/install.mjs'; import {decryptEnvelope} from '../scripts/enterprise-auth/decrypt-envelope.mjs'; import {executeSecure} from '../skills/ksf-workshop-runtime/scripts/ksf-secure.mjs'; import {APP,COMPANY,AGENT,HOST,SKILL,SCOPES,WRAPPER_SHA,sha,encode} from '../scripts/enterprise-auth/common.mjs'; const ROOT=path.dirname(path.dirname(fileURLToPath(import.meta.url))); const pair=crypto.generateKeyPairSync('rsa',{modulusLength:3072}); const recipient={schema:'ksf.enterprise-workshop-recipient.v1',publicOnly:true,companyObjectId:COMPANY,appId:APP, agentId:AGENT,host:HOST,keyDirectory:'/opt/data/ksf-key-receive-20261031-fixture', publicKeyPem:pair.publicKey.export({type:'spki',format:'pem'}), publicKeySha256:sha(pair.publicKey.export({type:'spki',format:'der'})),privateKeyExported:false,tokenExported:false}; const write=(file,body)=>{fs.mkdirSync(path.dirname(file),{recursive:true,mode:0o700});fs.writeFileSync(file,body,{mode:0o600});}; function fixture(t){ const base=fs.mkdtempSync(path.join(os.tmpdir(),'ksf-auth-test-')); t.after(()=>fs.rmSync(base,{recursive:true,force:true})); const recipientFile=path.join(base,'recipient.json');write(recipientFile,encode(recipient)); return{base,recipientFile,output:path.join(base,'private-issuance')}; } function fakeApi(f,options={}){ let row,token;const writes=[],calls=[]; return{ writes,calls,get row(){return row;},get token(){return token;}, request:async(method,route,body)=>{ calls.push([method,route]); assert.ok(route.startsWith('/classes/KsfServiceCredential'),'no business classes written'); if(method==='GET')return route.includes('?')?{results:row?[structuredClone(row)]:[]}:structuredClone(row); writes.push([method,structuredClone(body)]); if(method==='POST'){assert.equal(body.enabled,false);row={...structuredClone(body),objectId:'newCred123'};return{objectId:row.objectId};} if(method==='PUT'){ assert.ok(fs.existsSync(path.join(f.output,'delivery/FILES.sha256')),'encrypted delivery exists before enable'); if(options.failEnable)throw Object.assign(Error(),{code:'ENABLE_UNCERTAIN'}); Object.assign(row,body);return{updatedAt:'2026-11-10T00:00:00.000Z'}; } throw Error('unexpected request'); }, invoke:async(name,params,headers)=>{ const candidate=headers['X-Ksf-Service-Token']; if(!candidate||candidate.startsWith('invalid-control-'))return{http:401,body:{result:{ok:false,errors:[{code:'AUTH_REQUIRED'}]}}}; token=headers['X-Ksf-Service-Token'];assert.equal(sha(token),row.tokenHash);assert.ok(row.enabled); assert.deepEqual(Object.keys(headers).sort(),['Content-Type','X-Ksf-Service-Token','X-Parse-Application-Id'].sort()); if(name==='ksfGetIngestContract')return{http:200,body:{result:{ok:true,data:{workshop:{version:'ksf.workshop.v1'}}}}}; assert.equal(name,'ksfGetRecord');assert.equal(params.className,'KfSource'); return{http:400,body:{result:{ok:false,errors:[{code:'REFERENCE_NOT_FOUND'}]}}}; } }; } function target(f){ const dataDir=path.join(f.base,'target'); write(path.join(dataDir,'.fmode/config/enterprise/current.json'),encode({companyObjectId:COMPANY,appId:APP,provisionStatus:'success'})); const skill=path.join(dataDir,'skills/ksf-workshop-runtime'); for(const n of ['SKILL.md','scripts/ksf-secure.mjs'])write(path.join(skill,n),fs.readFileSync(path.join(ROOT,'skills/ksf-workshop-runtime',n))); write(path.join(dataDir,path.posix.basename(recipient.keyDirectory),'recipient-private.pem'),pair.privateKey.export({type:'pkcs8',format:'pem'})); return{dataDir,skill,hostname:HOST,platform:'linux'}; } const contractChild=()=>({status:0,stdout:JSON.stringify({ok:true,wrapperSha256:WRAPPER_SHA,credentialLoadedForChild:true, credentialWrittenToDisk:false,entryResult:{readOnly:true,result:{workshop:{version:'ksf.workshop.v1'}}}}),stderr:''}); test('plan neither creates a service credential nor writes an output directory',async t=>{ const f=fixture(t),api=fakeApi(f),result=await issue({...f,apply:false},api); assert.equal(result.planOnly,true);assert.deepEqual(result.scopes,SCOPES); assert.equal(fs.existsSync(f.output),false);assert.equal(api.writes.length,0); }); test('fresh issuance enables only a recoverable encrypted credential; no plaintext is persisted',async t=>{ const f=fixture(t),api=fakeApi(f),result=await issue({...f,apply:true},api); assert.equal(result.credentialId,'newCred123');assert.equal(result.authorizationRecordWrites,2); assert.deepEqual(api.row.scopes,['data:read','source:write','ingest:write']); assert.equal(api.row.scopes.includes('*'),false);assert.equal(api.row.scopes.includes('data:read-all'),false); const delivery=validateDelivery(result.deliveryDirectory,result.bundleManifestSha256); const payload=decryptEnvelope(delivery.envelope,pair.privateKey,{host:HOST,directory:recipient.keyDirectory,publicKeySha256:recipient.publicKeySha256}); assert.equal(payload.credentialId,api.row.objectId);assert.equal(payload.env.KSF_SERVICE_TOKEN,api.token); for(const item of fs.readdirSync(f.output,{recursive:true,withFileTypes:true})){ if(item.isFile()){ const raw=fs.readFileSync(path.join(item.parentPath,item.name)); assert.equal(raw.includes(Buffer.from(api.token)),false);assert.equal(raw.includes(Buffer.from('-----BEGIN PRIVATE KEY-----')),false); } } assert.equal(JSON.stringify(result).includes(api.token),false); }); test('repeated issuance returns the same ID with no second create or rotation',async t=>{ const f=fixture(t),api=fakeApi(f);const first=await issue({...f,apply:true},api); const second=await issue({...f,apply:true},api); assert.equal(second.credentialId,first.credentialId);assert.equal(second.alreadyIssued,true);assert.equal(api.writes.length,2); }); test('interrupted enable leaves an encrypted recoverable delivery and stops an ambiguous replay',async t=>{ const f=fixture(t),api=fakeApi(f,{failEnable:true}); await assert.rejects(issue({...f,apply:true},api),{code:'ENABLE_UNCERTAIN'}); assert.equal(api.row.enabled,false);assert.ok(fs.existsSync(path.join(f.output,'delivery/credential-envelope.json'))); await assert.rejects(issue({...f,apply:true},api),{code:'INCOMPLETE_ISSUANCE_REQUIRES_RECONCILIATION'}); assert.equal(api.writes.filter(x=>x[0]==='POST').length,1); }); test('an existing server credential without its journal is not silently adopted',async t=>{ const f=fixture(t),api=fakeApi(f);await issue({...f,apply:true},api); fs.renameSync(f.output,f.output+'-saved'); await assert.rejects(issue({...f,apply:true},api),{code:'EXISTING_SERVICE_CREDENTIAL_REQUIRES_RECONCILIATION'}); assert.equal(api.writes.length,2); }); test('recipient host, enterprise app and public-key substitution fail before an API mutation',async t=>{ for(const change of [{host:'043bb9231c09'},{appId:'FKieRbIoGtmain'},{publicKeySha256:'0'.repeat(64)}]){ const f=fixture(t),api=fakeApi(f);write(f.recipientFile,encode({...recipient,...change})); await assert.rejects(issue({...f,apply:true},api));assert.equal(api.writes.length,0);assert.equal(api.calls.length,0); } }); test('changed delivery manifest is rejected even when its file names remain plausible',async t=>{ const f=fixture(t),api=fakeApi(f),r=await issue({...f,apply:true},api); write(path.join(r.deliveryDirectory,'credential-envelope.json'),Buffer.from('{}\n')); await assert.rejects(issue({...f,apply:true},api),{code:'DELIVERY_FILE_MISMATCH'}); assert.throws(()=>validateDelivery(r.deliveryDirectory,r.bundleManifestSha256),{code:'DELIVERY_FILE_MISMATCH'}); }); test('recipient public export uses the target own key and repeats without changing it',t=>{ const f=fixture(t),deps=target(f),output=path.join(deps.dataDir,'public/recipient.json'); exportRecipient({keyDirectory:recipient.keyDirectory,output},deps); const first=fs.readFileSync(output);exportRecipient({output},deps);assert.deepEqual(fs.readFileSync(output),first); assert.equal(JSON.parse(first).publicKeySha256,recipient.publicKeySha256);assert.equal(first.includes(Buffer.from('PRIVATE KEY')),false); }); test('recipient export can generate its own key without using another agent identity',t=>{ const f=fixture(t),deps=target(f),output=path.join(deps.dataDir,'public/new.json'); exportRecipient({output},deps);const r=JSON.parse(fs.readFileSync(output)); assert.notEqual(r.publicKeySha256,recipient.publicKeySha256); assert.ok(fs.existsSync(path.join(deps.dataDir,path.posix.basename(r.keyDirectory),'recipient-private.pem'))); }); test('target install plan decrypts successfully without writing the binding',async t=>{ const f=fixture(t),api=fakeApi(f),r=await issue({...f,apply:true},api),deps=target(f); const result=await install({bundle:r.deliveryDirectory,manifestSha:r.bundleManifestSha256},deps); assert.equal(result.planOnly,true);assert.equal(fs.existsSync(path.join(deps.skill,'credential-binding.json')),false); }); test('installation preserves the frozen wrapper, exercises it and permits identical replay',async t=>{ const f=fixture(t),api=fakeApi(f),r=await issue({...f,apply:true},api),deps=target(f);let calls=0; const run={...deps,spawn:(node,argv)=>{calls++;assert.equal(argv[1],'workshop-contract');return contractChild();}, controls:async env=>{assert.equal(env.KSF_SERVICE_TOKEN,api.token);return[{identity:'test-fixture',http:400}];}}; const options={bundle:r.deliveryDirectory,manifestSha:r.bundleManifestSha256,apply:true}; const first=await install(options,run),second=await install(options,run); assert.equal(first.workshopContractVerified,true);assert.equal(second.alreadyBound,true);assert.equal(calls,2); assert.equal(sha(fs.readFileSync(path.join(deps.skill,'scripts/ksf-secure.mjs'))),WRAPPER_SHA); assert.equal(first.saveReadbackVerified,false); }); test('unknown binding or wrong container cannot be overwritten by the installer',async t=>{ const f=fixture(t),api=fakeApi(f),r=await issue({...f,apply:true},api),deps=target(f); const o={bundle:r.deliveryDirectory,manifestSha:r.bundleManifestSha256,apply:true}; await assert.rejects(install(o,{...deps,hostname:'043bb9231c09'}),{code:'WRONG_CONTAINER'}); write(path.join(deps.skill,'credential-binding.json'),Buffer.from('{"keep":"existing"}')); await assert.rejects(install(o,deps),{code:'EXISTING_BINDING_CHANGED'}); assert.equal(fs.existsSync(path.join(deps.dataDir,'ksf-enterprise-auth-'+r.credentialId)),false); }); test('installer rejects a different private key before installing a binding',async t=>{ const f=fixture(t),api=fakeApi(f),r=await issue({...f,apply:true},api),deps=target(f); const other=crypto.generateKeyPairSync('rsa',{modulusLength:3072}); write(path.join(deps.dataDir,path.posix.basename(recipient.keyDirectory),'recipient-private.pem'),other.privateKey.export({type:'pkcs8',format:'pem'})); await assert.rejects(install({bundle:r.deliveryDirectory,manifestSha:r.bundleManifestSha256,apply:true},deps),{code:'KEY_FINGERPRINT_MISMATCH'}); assert.equal(fs.existsSync(path.join(deps.skill,'credential-binding.json')),false); }); test('failed live contract does not claim readiness and an identical install can resume',async t=>{ const f=fixture(t),api=fakeApi(f),r=await issue({...f,apply:true},api),deps=target(f); const options={bundle:r.deliveryDirectory,manifestSha:r.bundleManifestSha256,apply:true}; await assert.rejects(install(options,{...deps,spawn:()=>({status:1,stdout:'',stderr:'{}'})}),{code:'FROZEN_ENTRY_CONTRACT_FAILED'}); const resumed=await install(options,{...deps,spawn:contractChild,controls:async()=>[]}); assert.equal(resumed.alreadyBound,true);assert.equal(resumed.workshopContractVerified,true); }); test('the frozen secure wrapper decrypts the newly issued envelope and passes token only to its child',async t=>{ const f=fixture(t),api=fakeApi(f),r=await issue({...f,apply:true},api); const delivery=validateDelivery(r.deliveryDirectory,r.bundleManifestSha256),argv=['workshop-contract','--input','/opt/data/input.json','--request-id','test-new-agent']; const skillDir=path.join(ROOT,'skills/ksf-workshop-runtime'); const entry=path.join(skillDir,'scripts/ksf-workshop.mjs'),entryHash=sha(fs.readFileSync(entry)); let childToken; const result=await executeSecure(argv,{skillDir,hostname:HOST,readPrivateKey:()=>pair.privateKey, readBytes:file=>{ if(path.basename(file)==='credential-binding.json')return delivery.files['credential-binding.json']; if(file===delivery.binding.envelopeFile)return delivery.files['credential-envelope.json']; if(file===delivery.binding.decryptModule)return delivery.files['decrypt-envelope.mjs']; return fs.readFileSync(file); },importDecrypt:async()=>({decryptEnvelope}),spawn:(node,args,options)=>{ childToken=options.env.KSF_SERVICE_TOKEN; return{status:0,stdout:JSON.stringify({skill:'ksf-workshop-runtime',entry,entrySha256:entryHash,command:'workshop-contract', invocationId:crypto.randomUUID(),requestId:'test-new-agent',ok:true}),stderr:''}; }}); assert.equal(childToken,api.token);assert.equal(result.credentialWrittenToDisk,false);assert.equal(JSON.stringify(result).includes(api.token),false); });