deadbyte-mcp 0.15.72 → 0.15.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/MANIFEST.SHA256 +75 -27
  2. package/PROVENANCE.json +42 -14
  3. package/README.txt +24 -18
  4. package/RELEASE.json +52 -18
  5. package/SBOM.cdx.json +14 -2
  6. package/TEST-MATRIX.json +30 -2
  7. package/bin/deadbyte-owner-token-r193.exe +0 -0
  8. package/bridge/package.json +1 -1
  9. package/controller/deadbyte-process-policy.json +4 -4
  10. package/docs/R184-package-lock.json +2 -2
  11. package/native/deadbyte-owner-token-r193.cpp +156 -0
  12. package/package.json +2 -2
  13. package/scripts/gate-windows-r193.ps1 +108 -0
  14. package/scripts/gate-windows-r194.ps1 +112 -0
  15. package/scripts/npm-interactive-r194.mjs +13 -0
  16. package/scripts/npm-publication-r65.mjs +64 -4
  17. package/scripts/npm-release-r48.mjs +58 -11
  18. package/scripts/npm-release-readiness-r193.mjs +80 -0
  19. package/scripts/npm-release-readiness-r194.mjs +80 -0
  20. package/scripts/r188-owner-uac-review.ps1 +91 -0
  21. package/scripts/r188-uac-review-preview.mjs +65 -0
  22. package/scripts/r193-compile-token.ps1 +22 -0
  23. package/scripts/r193-evidence-relocate.ps1 +12 -0
  24. package/scripts/r193-focused-gate.mjs +20 -0
  25. package/scripts/r193-import-r188-scripts.ps1 +14 -0
  26. package/scripts/r193-limited-subject-probe.ps1 +25 -0
  27. package/scripts/r193-migrate-runtime-limited.ps1 +103 -0
  28. package/scripts/r193-owner-keygen.mjs +43 -0
  29. package/scripts/r193-owner-request-live.mjs +50 -0
  30. package/scripts/r193-owner-uac-approve.ps1 +42 -0
  31. package/scripts/r193-owner-uac-broker.mjs +139 -0
  32. package/scripts/r193-owner-uac-enroll-and-approve.ps1 +62 -0
  33. package/scripts/r193-test-limited-token.ps1 +49 -0
  34. package/scripts/r193-toolchain-inventory.ps1 +7 -0
  35. package/scripts/r193-uac-bridge-focused.mjs +21 -0
  36. package/src/r188-owner-uac.mjs +105 -0
  37. package/src/r188-uac-boundary.mjs +21 -0
  38. package/src/r193-live-owner-subject.mjs +110 -0
  39. package/src/r193-owner-secret-acl.mjs +67 -0
  40. package/src/r193-owner-uac-broker.mjs +85 -0
  41. package/src/r193-uac-r70-bridge.mjs +54 -0
  42. package/src/version.mjs +1 -1
  43. package/test/process-policy-refresh.test.mjs +1 -1
  44. package/test/r130-release-security-contract.test.mjs +8 -8
  45. package/test/r132-release-identity.test.mjs +7 -7
  46. package/test/r153-prepublish-identity.test.mjs +1 -1
  47. package/test/r160-release-contract.test.mjs +3 -3
  48. package/test/r165-live-cli-skew.test.mjs +1 -1
  49. package/test/r167-release-contract.test.mjs +11 -11
  50. package/test/r168-release-contract.test.mjs +4 -4
  51. package/test/r172-release-contract.test.mjs +6 -6
  52. package/test/r173-release-contract.test.mjs +16 -16
  53. package/test/r179-release-contract.test.mjs +11 -11
  54. package/test/r188-owner-uac.test.mjs +48 -0
  55. package/test/r188-uac-boundary.test.mjs +42 -0
  56. package/test/r190-release-contract.test.mjs +10 -10
  57. package/test/r191-release-contract.test.mjs +12 -12
  58. package/test/r192-release-identity.test.mjs +10 -10
  59. package/test/r193-limited-migration-contract.test.mjs +26 -0
  60. package/test/r193-live-owner-subject.test.mjs +61 -0
  61. package/test/r193-native-process-observer.test.mjs +36 -0
  62. package/test/r193-native-token.test.mjs +43 -0
  63. package/test/r193-owner-enrollment-entrypoint.test.mjs +38 -0
  64. package/test/r193-owner-secret-acl.test.mjs +23 -0
  65. package/test/r193-owner-uac-broker.test.mjs +82 -0
  66. package/test/r193-owner-uac-entrypoint.test.mjs +36 -0
  67. package/test/r193-release-identity.test.mjs +56 -0
  68. package/test/r193-release-readiness.test.mjs +87 -0
  69. package/test/r193-uac-r70-bridge.test.mjs +88 -0
  70. package/test/r193-windows-gate.test.mjs +30 -0
  71. package/test/r194-npm-auth-recovery.test.mjs +77 -0
  72. package/test/r194-npm-preauth.test.mjs +57 -0
  73. package/test/r194-release-identity.test.mjs +43 -0
  74. package/test/r194-release-readiness.test.mjs +87 -0
  75. package/test/r194-windows-gate.test.mjs +21 -0
  76. package/test/r59-tool-surface-compat.test.mjs +1 -1
@@ -0,0 +1,43 @@
1
+ // One-time protected owner key enrollment. No caller-selected paths.
2
+ import {generateKeyPairSync} from 'node:crypto';
3
+ import {lstat,open,readFile} from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import {fileURLToPath} from 'node:url';
6
+ import {canonicalJson} from '../src/canonical-json.mjs';
7
+ import {createR186OwnerAnchor} from '../src/r186-owner-anchor.mjs';
8
+ import {inspectTrustedInstallation} from '../src/privileged-install-trust-r89.mjs';
9
+ import {inspectR193OwnerSecretAcl} from '../src/r193-owner-secret-acl.mjs';
10
+ import {parseManifest,verifyManifestTreeExact} from '../src/release-slot.mjs';
11
+ const THIS=fileURLToPath(import.meta.url),ROOT=path.resolve(path.dirname(THIS),'..');
12
+ const OWNER='C:\\Program Files\\DEADBYTE-OwnerAuthority';
13
+ const PRIVATE=path.win32.join(OWNER,'owner-private.der');
14
+ const PUBLIC=path.win32.join(OWNER,'owner-public.pem');
15
+ const ANCHOR=path.win32.join(OWNER,'owner-anchor.json');
16
+ async function exclusive(file,bytes){
17
+ const handle=await open(file,'wx',0o600);
18
+ try{await handle.writeFile(bytes);await handle.sync();}finally{await handle.close();}
19
+ }
20
+ async function main(){
21
+ if(process.platform!=='win32'||process.arch!=='x64')throw Error('R193 owner keygen requires Windows x64');
22
+ if(process.argv.length!==2)throw Error('R193 owner keygen accepts no arguments');
23
+ await inspectTrustedInstallation(['C:\\Program Files\\nodejs\\node.exe',THIS,
24
+ path.join(ROOT,'MANIFEST.SHA256'),path.join(ROOT,'src','r186-owner-anchor.mjs'),
25
+ path.join(ROOT,'src','r193-owner-secret-acl.mjs'),
26
+ path.join(ROOT,'src','privileged-install-trust-r89.mjs'),
27
+ path.join(ROOT,'src','release-slot.mjs')]);
28
+ const manifest=await readFile(path.join(ROOT,'MANIFEST.SHA256'),'utf8');
29
+ await verifyManifestTreeExact(ROOT,parseManifest(manifest));
30
+ const owner=await lstat(OWNER);
31
+ if(!owner.isDirectory()||owner.isSymbolicLink())throw Error('R193 owner directory is not a real directory');
32
+ const pair=generateKeyPairSync('ed25519');
33
+ const privateDer=pair.privateKey.export({format:'der',type:'pkcs8'});
34
+ const material=createR186OwnerAnchor(pair.publicKey.export({format:'pem',type:'spki'}).toString());
35
+ await exclusive(PRIVATE,privateDer);
36
+ await exclusive(PUBLIC,Buffer.from(material.public_key_pem,'utf8'));
37
+ await exclusive(ANCHOR,Buffer.from(canonicalJson(material.anchor)+'\n','utf8'));
38
+ const secret=await inspectR193OwnerSecretAcl([OWNER,PRIVATE]);
39
+ process.stdout.write(JSON.stringify({status:'R193_OWNER_AUTHORITY_ENROLLED',
40
+ owner_key_id:material.anchor.owner_key_id,secret_acl:secret.reason,
41
+ private_key_exported:false,authority_granted:false})+'\n');
42
+ }
43
+ main().catch(error=>{console.error(String(error?.message??error).slice(0,500));process.exitCode=2;});
@@ -0,0 +1,50 @@
1
+ // Protected, fixed-scope request generation after Limited migration.
2
+ import {createHash} from 'node:crypto';
3
+ import {execFile} from 'node:child_process';
4
+ import {promisify} from 'node:util';
5
+ import {lstat,open,readFile} from 'node:fs/promises';
6
+ import path from 'node:path';
7
+ import {fileURLToPath} from 'node:url';
8
+ import {canonicalJson} from '../src/canonical-json.mjs';
9
+ import {inspectTrustedInstallation} from '../src/privileged-install-trust-r89.mjs';
10
+ import {parseManifest,verifyManifestTreeExact} from '../src/release-slot.mjs';
11
+ import {createR188OwnerUacRequest} from '../src/r188-owner-uac.mjs';
12
+ import {createR193LiveMachineEpoch} from '../src/r193-live-owner-subject.mjs';
13
+ const execFileAsync=promisify(execFile);
14
+ const THIS=fileURLToPath(import.meta.url),ROOT=path.resolve(path.dirname(THIS),'..');
15
+ const STATE='C:\\Users\\DEADBYTE\\.deadbyte-mcp',RUNTIME=path.win32.join(STATE,'runtime');
16
+ const PS='C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe';
17
+ const sha=b=>createHash('sha256').update(b).digest('hex');
18
+ async function bounded(file,limit){const s=await lstat(file);if(!s.isFile()||s.isSymbolicLink()||s.size<1||s.size>limit)throw Error('R193 request input unsafe');return readFile(file);}
19
+ async function main(){
20
+ if(process.platform!=='win32'||process.arch!=='x64'||process.argv.length!==2)throw Error('R193 live request accepts no arguments');
21
+ const manifestPath=path.join(ROOT,'MANIFEST.SHA256');
22
+ await inspectTrustedInstallation(['C:\\Program Files\\nodejs\\node.exe',THIS,manifestPath,
23
+ path.join(ROOT,'src','r188-owner-uac.mjs'),path.join(ROOT,'src','r193-live-owner-subject.mjs'),
24
+ path.join(ROOT,'src','privileged-install-trust-r89.mjs')]);
25
+ const manifestBytes=await bounded(manifestPath,1024*1024);
26
+ await verifyManifestTreeExact(ROOT,parseManifest(manifestBytes.toString('utf8')));
27
+ const pointer=JSON.parse((await bounded(path.win32.join(STATE,'active-release.json'),64*1024)).toString('utf8'));
28
+ if(pointer.manifest_sha256!==sha(manifestBytes))throw Error('R193 request package is not exact active release');
29
+ const codingBytes=await bounded(path.win32.join(pointer.generation_root,'coding-policy.json'),1024*1024);
30
+ const autonomousBytes=await bounded(path.win32.join(pointer.generation_root,'autonomous-policy.json'),1024*1024);
31
+ const coding=JSON.parse(codingBytes),autonomous=JSON.parse(autonomousBytes);
32
+ if(!coding.roots?.core?.path||!Array.isArray(autonomous.root_ids)||autonomous.root_ids.length!==1||autonomous.root_ids[0]!=='core')
33
+ throw Error('R193 request policy root is not the bounded core project');
34
+ const env={...process.env,DEADBYTE_CONTROLLER_CONFIG:pointer.config_path,DEADBYTE_CONTROLLER_RUNTIME_ROOT:RUNTIME};
35
+ const controller=path.join(ROOT,'controller','deadbyte-controller.ps1');
36
+ const {stdout}=await execFileAsync(PS,['-NoLogo','-NoProfile','-NonInteractive','-ExecutionPolicy','Bypass','-File',controller,'status','-Json'],
37
+ {env,windowsHide:true,timeout:20000,maxBuffer:1024*1024,encoding:'utf8'});
38
+ const observation=JSON.parse(stdout);
39
+ if(observation.state!=='ONLINE'||!observation.supervisor?.running)throw Error('R193 request requires ONLINE Limited runtime');
40
+ const machineEpoch=createR193LiveMachineEpoch({activePointer:pointer,controllerObservation:observation});
41
+ const request=createR188OwnerUacRequest({machineEpoch,releaseManifestSha256:sha(manifestBytes),
42
+ codingPolicySha256:sha(codingBytes),autonomousPolicySha256:sha(autonomousBytes),
43
+ rootId:'core',projectRoot:coding.roots.core.path,maxSeconds:600,now:new Date(),expiresInMs:300000});
44
+ const out=path.win32.join(RUNTIME,'owner-consent','r193-request-'+request.request_sha256+'.json');
45
+ const handle=await open(out,'wx',0o600);try{await handle.writeFile(canonicalJson(request)+'\n');await handle.sync();}finally{await handle.close();}
46
+ process.stdout.write(JSON.stringify({status:'R193_OWNER_REQUEST_CREATED',request_path:out,
47
+ request_sha256:request.request_sha256,review_phrase:request.review_phrase,
48
+ expires_at_utc:request.subject.expires_at_utc,authority_granted:false})+'\n');
49
+ }
50
+ main().catch(error=>{console.error(String(error?.message??error).slice(0,500));process.exitCode=2;});
@@ -0,0 +1,42 @@
1
+ #requires -Version 5.1
2
+ #requires -RunAsAdministrator
3
+ [CmdletBinding()]
4
+ param([Parameter(Mandatory=$true)][string]$RequestPath)
5
+ $ErrorActionPreference='Stop';Set-StrictMode -Version Latest
6
+ $root=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
7
+ $program=[IO.Path]::GetFullPath($env:ProgramFiles).TrimEnd('\')+'\'
8
+ if(-not ($root.TrimEnd('\')+'\').StartsWith($program,[StringComparison]::OrdinalIgnoreCase)){
9
+ throw 'R193 owner broker must run from an R89-protected Program Files package'
10
+ }
11
+ if(-not [Environment]::UserInteractive){throw 'R193 owner approval requires an interactive desktop'}
12
+ $node='C:\Program Files\nodejs\node.exe'
13
+ $broker=Join-Path $root 'scripts\r193-owner-uac-broker.mjs'
14
+ $request=[IO.Path]::GetFullPath($RequestPath)
15
+ $raw=@(& $node $broker preflight $request 2>&1) -join [Environment]::NewLine
16
+ if($LASTEXITCODE -ne 0){throw ('R193 preflight blocked: '+$raw.Substring(0,[Math]::Min(500,$raw.Length)))}
17
+ $preview=$raw|ConvertFrom-Json
18
+ if([string]$preview.status -cne 'READY_FOR_OWNER_GESTURE' -or $preview.authority_granted -or $preview.owner_approved){
19
+ throw 'R193 owner preflight returned an invalid state'
20
+ }
21
+ Write-Host '';Write-Host 'DEADBYTE R193 / OWNER AUTONOMOUS APPROVAL' -ForegroundColor Yellow
22
+ Write-Host 'This signs one short-lived exact request. It does not itself arm Autonomous.'
23
+ Write-Host ('Request SHA-256: '+[string]$preview.request_sha256)
24
+ Write-Host ('Project: '+[string]$preview.project_root)
25
+ Write-Host ('Operation: '+[string]$preview.operation)
26
+ Write-Host ('Duration cap seconds: '+[string]$preview.max_seconds)
27
+ Write-Host ('Expires UTC: '+[string]$preview.expires_at_utc)
28
+ $phrase=[string]$preview.review_phrase
29
+ $entered=Read-Host ('Type '+$phrase+' to approve this exact request')
30
+ if($entered -cne $phrase){throw 'R193 owner rejected request'}
31
+ $owner='C:\Program Files\DEADBYTE-OwnerAuthority'
32
+ if(-not(Test-Path -LiteralPath $owner -PathType Container)){throw 'R193 owner authority is not enrolled'}
33
+ $gesture=[ordered]@{schema='deadbyte.r193-owner-gesture.v1';status='APPROVED';
34
+ request_sha256=[string]$preview.request_sha256;review_phrase=$phrase;
35
+ approved_at_utc=[DateTime]::UtcNow.ToString('o')}
36
+ $gesturePath=Join-Path $owner ('gesture-'+[string]$preview.request_sha256+'.json')
37
+ $bytes=(New-Object Text.UTF8Encoding($false)).GetBytes(($gesture|ConvertTo-Json -Compress)+[Environment]::NewLine)
38
+ $stream=[IO.File]::Open($gesturePath,[IO.FileMode]::CreateNew,[IO.FileAccess]::Write,[IO.FileShare]::None)
39
+ try{$stream.Write($bytes,0,$bytes.Length);$stream.Flush($true)}finally{$stream.Dispose()}
40
+ $out=@(& $node $broker approve $request 2>&1) -join [Environment]::NewLine
41
+ if($LASTEXITCODE -ne 0){throw ('R193 signing blocked: '+$out.Substring(0,[Math]::Min(500,$out.Length)))}
42
+ Write-Output $out
@@ -0,0 +1,139 @@
1
+ // Protected R193 owner broker. This entrypoint is intentionally fixed to the
2
+ // local DEADBYTE state and owner-authority roots; callers choose only an exact
3
+ // request file. It never issues authority. The R186 transaction remains the
4
+ // sole grant/epoch mutation boundary.
5
+ import {createHash,createPrivateKey,createPublicKey} from 'node:crypto';
6
+ import {execFile} from 'node:child_process';
7
+ import {promisify} from 'node:util';
8
+ import {lstat,mkdir,open,readFile} from 'node:fs/promises';
9
+ import path from 'node:path';
10
+ import {fileURLToPath} from 'node:url';
11
+ import {canonicalJson} from '../src/canonical-json.mjs';
12
+ import {inspectTrustedInstallation} from '../src/privileged-install-trust-r89.mjs';
13
+ import {parseManifest,verifyManifestTreeExact} from '../src/release-slot.mjs';
14
+ import {buildR193LiveOwnerBoundary} from '../src/r193-live-owner-subject.mjs';
15
+ import {approveR193OwnerRequest} from '../src/r193-owner-uac-broker.mjs';
16
+ import {createR186OwnerAnchor} from '../src/r186-owner-anchor.mjs';
17
+ import {inspectR193OwnerSecretAcl} from '../src/r193-owner-secret-acl.mjs';
18
+
19
+ const execFileAsync=promisify(execFile);
20
+ const THIS=fileURLToPath(import.meta.url),ROOT=path.resolve(path.dirname(THIS),'..');
21
+ const STATE='C:\\Users\\DEADBYTE\\.deadbyte-mcp';
22
+ const RUNTIME=path.win32.join(STATE,'runtime');
23
+ const OWNER='C:\\Program Files\\DEADBYTE-OwnerAuthority';
24
+ const PRIVATE=path.win32.join(OWNER,'owner-private.der');
25
+ const PUBLIC=path.win32.join(OWNER,'owner-public.pem');
26
+ const ANCHOR=path.win32.join(OWNER,'owner-anchor.json');
27
+ const NATIVE=path.join(ROOT,'bin','deadbyte-owner-token-r193.exe');
28
+ const PS='C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe';
29
+ const NODE='C:\\Program Files\\nodejs\\node.exe';
30
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
31
+ const block=reason=>{throw new Error('R193_OWNER_UAC_BROKER_BLOCKED: '+reason);};
32
+ async function bounded(file,limit){
33
+ const stat=await lstat(file);
34
+ if(!stat.isFile()||stat.isSymbolicLink()||stat.size<1||stat.size>limit)block('unsafe input: '+path.basename(file));
35
+ return readFile(file);
36
+ }
37
+ async function exclusive(file,bytes){
38
+ await mkdir(path.dirname(file),{recursive:true});
39
+ const handle=await open(file,'wx',0o600);
40
+ try{await handle.writeFile(bytes);await handle.sync();}finally{await handle.close();}
41
+ }
42
+ async function exactOrWrite(file,bytes){
43
+ try{await exclusive(file,bytes);return 'CREATED';}
44
+ catch(error){
45
+ if(error?.code!=='EEXIST')throw error;
46
+ if(!(await readFile(file)).equals(bytes))block('existing output differs: '+path.basename(file));
47
+ return 'ALREADY_EXACT';
48
+ }
49
+ }
50
+ async function jsonExec(file,args,options={}){
51
+ const {stdout}=await execFileAsync(file,args,{windowsHide:true,timeout:20000,
52
+ maxBuffer:1024*1024,encoding:'utf8',...options});
53
+ try{return JSON.parse(stdout);}catch{block('invalid JSON from protected child');}
54
+ }
55
+ async function uacPolicy(){
56
+ const command=`$p=Get-ItemProperty -LiteralPath 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System';[pscustomobject]@{enable_uac=([int]$p.EnableLUA -eq 1);secure_desktop=([int]$p.PromptOnSecureDesktop -eq 1);prompt_mode=$(if([int]$p.ConsentPromptBehaviorAdmin -eq 0){'silent'}else{'explicit_secure_desktop'})}|ConvertTo-Json -Compress`;
57
+ return jsonExec(PS,['-NoLogo','-NoProfile','-NonInteractive','-Command',command]);
58
+ }
59
+ async function live(request){
60
+ const manifestPath=path.join(ROOT,'MANIFEST.SHA256');
61
+ const protectedFiles=[NODE,THIS,manifestPath,NATIVE,
62
+ path.join(ROOT,'src','r193-live-owner-subject.mjs'),
63
+ path.join(ROOT,'src','r193-owner-uac-broker.mjs'),
64
+ path.join(ROOT,'src','r193-uac-r70-bridge.mjs'),
65
+ path.join(ROOT,'src','r193-owner-secret-acl.mjs'),
66
+ path.join(ROOT,'src','r188-owner-uac.mjs'),
67
+ path.join(ROOT,'src','r70-owner-approval.mjs'),
68
+ path.join(ROOT,'src','canonical-json.mjs'),
69
+ path.join(ROOT,'src','privileged-install-trust-r89.mjs'),
70
+ path.join(ROOT,'src','release-slot.mjs')];
71
+ const installation=await inspectTrustedInstallation(protectedFiles);
72
+ const manifestBytes=await bounded(manifestPath,1024*1024);
73
+ await verifyManifestTreeExact(ROOT,parseManifest(manifestBytes.toString('utf8')));
74
+ const pointer=JSON.parse((await bounded(path.win32.join(STATE,'active-release.json'),64*1024)).toString('utf8'));
75
+ if(pointer.manifest_sha256!==sha(manifestBytes))block('protected package is not exact active release');
76
+ const generation=pointer.generation_root;
77
+ const codingPath=path.win32.join(generation,'coding-policy.json');
78
+ const autonomousPath=path.win32.join(generation,'autonomous-policy.json');
79
+ const configPath=pointer.config_path;
80
+ const controller=path.join(ROOT,'controller','deadbyte-controller.ps1');
81
+ const env={...process.env,DEADBYTE_CONTROLLER_CONFIG:configPath,
82
+ DEADBYTE_CONTROLLER_RUNTIME_ROOT:RUNTIME};
83
+ const observation=await jsonExec(PS,['-NoLogo','-NoProfile','-NonInteractive',
84
+ '-ExecutionPolicy','Bypass','-File',controller,'status','-Json'],{env});
85
+ const supervisor=JSON.parse((await bounded(path.win32.join(RUNTIME,'supervisor.instance.json'),64*1024)).toString('utf8'));
86
+ const sources={bridge:observation.bridge,core:observation.core,cloud:observation.cloud,supervisor};
87
+ const processReports={};
88
+ for(const component of ['bridge','core','cloud','supervisor'])
89
+ processReports[component]=await jsonExec(NATIVE,['--inspect-pid',String(sources[component]?.pid)]);
90
+ const [codingPolicyBytes,autonomousPolicyBytes,uac]=await Promise.all([
91
+ bounded(codingPath,1024*1024),bounded(autonomousPath,1024*1024),uacPolicy()]);
92
+ const built=buildR193LiveOwnerBoundary({request,activePointer:pointer,installedManifestBytes:manifestBytes,
93
+ codingPolicyBytes,autonomousPolicyBytes,controllerObservation:observation,
94
+ supervisorLedger:supervisor,processReports,brokerR89Trusted:installation.trusted,
95
+ keyAclTrusted:false,uac,ownerGesture:'pending',now:new Date()});
96
+ return {...built,pointer,manifestBytes,codingPolicyBytes,autonomousPolicyBytes,uac};
97
+ }
98
+ async function main(){
99
+ if(process.platform!=='win32'||process.arch!=='x64')block('Windows x64 required');
100
+ const [mode,requestPath]=process.argv.slice(2);
101
+ if(!['preflight','approve'].includes(mode)||process.argv.slice(2).length!==2||
102
+ !path.win32.isAbsolute(requestPath))block('usage: <preflight|approve> <absolute-request-json>');
103
+ await inspectTrustedInstallation([NODE,THIS,path.join(ROOT,'MANIFEST.SHA256'),NATIVE]);
104
+ const request=JSON.parse((await bounded(requestPath,64*1024)).toString('utf8'));
105
+ const state=await live(request);
106
+ if(mode==='preflight'){
107
+ process.stdout.write(JSON.stringify({status:'READY_FOR_OWNER_GESTURE',
108
+ request_sha256:request.request_sha256,review_phrase:request.review_phrase,
109
+ project_root:request.subject.project_root,operation:request.subject.operation,
110
+ max_seconds:request.subject.max_seconds,expires_at_utc:request.subject.expires_at_utc,
111
+ authority_granted:false,owner_approved:false})+'\n');
112
+ return;
113
+ }
114
+ const gesturePath=path.win32.join(OWNER,'gesture-'+request.request_sha256+'.json');
115
+ const gesture=JSON.parse((await bounded(gesturePath,16*1024)).toString('utf8'));
116
+ if(gesture?.schema!=='deadbyte.r193-owner-gesture.v1'||gesture?.status!=='APPROVED'||
117
+ gesture?.request_sha256!==request.request_sha256||gesture?.review_phrase!==request.review_phrase||
118
+ typeof gesture?.approved_at_utc!=='string'||Date.now()-Date.parse(gesture.approved_at_utc)<0||
119
+ Date.now()-Date.parse(gesture.approved_at_utc)>60000)block('owner gesture missing, stale or mismatched');
120
+ const secret=await inspectR193OwnerSecretAcl([OWNER,PRIVATE]);
121
+ const [privateKeyDer,publicPem,anchorBytes]=await Promise.all([
122
+ bounded(PRIVATE,8192),bounded(PUBLIC,8192),bounded(ANCHOR,4096)]);
123
+ const privateKey=createPrivateKey({key:privateKeyDer,format:'der',type:'pkcs8'});
124
+ const derived=createR186OwnerAnchor(createPublicKey(privateKey).export({format:'pem',type:'spki'}).toString());
125
+ const anchor=JSON.parse(anchorBytes.toString('utf8'));
126
+ if(derived.public_key_pem!==publicPem.toString('utf8')||
127
+ canonicalJson(derived.anchor)!==canonicalJson(anchor))block('owner key enrollment mismatch');
128
+ const result=approveR193OwnerRequest({request,expected:state.expected,privateKeyDer,
129
+ boundary:{...state.boundary,key_acl_trusted:secret.trusted,owner_gesture:'approved'},now:new Date()});
130
+ const bytes=Buffer.from(canonicalJson(result.approval)+'\n','utf8');
131
+ const protectedApproval=path.win32.join(OWNER,'approval-'+request.request_sha256+'.json');
132
+ const runtimeApproval=path.win32.join(RUNTIME,'owner-consent','autonomous-approval.json');
133
+ const protected_state=await exactOrWrite(protectedApproval,bytes);
134
+ const runtime_state=await exactOrWrite(runtimeApproval,bytes);
135
+ process.stdout.write(JSON.stringify({...result,approval:undefined,protected_state,runtime_state,
136
+ protected_approval_sha256:sha(bytes),protected_approval_path:protectedApproval,
137
+ runtime_approval_path:runtimeApproval})+'\n');
138
+ }
139
+ main().catch(error=>{console.error(String(error?.message??error).slice(0,600));process.exitCode=2;});
@@ -0,0 +1,62 @@
1
+ #requires -Version 5.1
2
+ #requires -RunAsAdministrator
3
+ [CmdletBinding()]
4
+ param([Parameter(Mandatory=$true)][string]$RequestPath)
5
+ $ErrorActionPreference='Stop';Set-StrictMode -Version Latest
6
+ $root=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
7
+ $program=[IO.Path]::GetFullPath($env:ProgramFiles).TrimEnd('\')+'\'
8
+ if(-not ($root.TrimEnd('\')+'\').StartsWith($program,[StringComparison]::OrdinalIgnoreCase)){
9
+ throw 'R193 enrollment must run from an R89-protected Program Files package'
10
+ }
11
+ if(-not [Environment]::UserInteractive){throw 'R193 enrollment requires an interactive owner desktop'}
12
+ $node='C:\Program Files\nodejs\node.exe'
13
+ $broker=Join-Path $root 'scripts\r193-owner-uac-broker.mjs'
14
+ $keygen=Join-Path $root 'scripts\r193-owner-keygen.mjs'
15
+ $request=[IO.Path]::GetFullPath($RequestPath)
16
+ $raw=@(& $node $broker preflight $request 2>&1) -join [Environment]::NewLine
17
+ if($LASTEXITCODE -ne 0){throw ('R193 enrollment preflight blocked: '+$raw.Substring(0,[Math]::Min(500,$raw.Length)))}
18
+ $preview=$raw|ConvertFrom-Json
19
+ if([string]$preview.status -cne 'READY_FOR_OWNER_GESTURE' -or $preview.authority_granted -or $preview.owner_approved){
20
+ throw 'R193 enrollment preflight returned an invalid state'
21
+ }
22
+ Write-Host '';Write-Host 'DEADBYTE R193 / ENROLL OWNER AUTHORITY' -ForegroundColor Yellow
23
+ Write-Host 'A new owner-only Ed25519 identity will be created under Program Files.'
24
+ Write-Host 'Limited DEADBYTE processes will not be able to read or use the private key.'
25
+ Write-Host ('Request SHA-256: '+[string]$preview.request_sha256)
26
+ Write-Host ('Project: '+[string]$preview.project_root)
27
+ Write-Host ('Duration cap seconds: '+[string]$preview.max_seconds)
28
+ $phrase=[string]$preview.review_phrase
29
+ $entered=Read-Host ('Type '+$phrase+' to enroll and approve this exact request')
30
+ if($entered -cne $phrase){throw 'R193 owner rejected enrollment'}
31
+ $owner='C:\Program Files\DEADBYTE-OwnerAuthority'
32
+ if(Test-Path -LiteralPath $owner){throw 'R193 owner authority already exists; use the approval-only workflow'}
33
+ $admins=New-Object Security.Principal.SecurityIdentifier('S-1-5-32-544')
34
+ $system=New-Object Security.Principal.SecurityIdentifier('S-1-5-18')
35
+ $inherit=[Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit'
36
+ $none=[Security.AccessControl.PropagationFlags]::None
37
+ $allow=[Security.AccessControl.AccessControlType]::Allow
38
+ New-Item -ItemType Directory -Path $owner -ErrorAction Stop | Out-Null
39
+ $acl=New-Object Security.AccessControl.DirectorySecurity
40
+ $acl.SetAccessRuleProtection($true,$false);$acl.SetOwner($admins)
41
+ $acl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($admins,'FullControl',$inherit,$none,$allow)))
42
+ $acl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($system,'FullControl',$inherit,$none,$allow)))
43
+ Set-Acl -LiteralPath $owner -AclObject $acl
44
+ # Keygen requires the directory to exist with its final ACL. It never accepts a
45
+ # target path and creates every key file with CreateNew/no-clobber semantics.
46
+ $keyRaw=@(& $node $keygen 2>&1) -join [Environment]::NewLine
47
+ if($LASTEXITCODE -ne 0){throw ('R193 protected key enrollment blocked: '+$keyRaw.Substring(0,[Math]::Min(500,$keyRaw.Length)))}
48
+ $keyResult=$keyRaw|ConvertFrom-Json
49
+ if([string]$keyResult.status -cne 'R193_OWNER_AUTHORITY_ENROLLED' -or $keyResult.private_key_exported -or $keyResult.authority_granted){
50
+ throw 'R193 key enrollment returned an invalid state'
51
+ }
52
+ Write-Host ('Owner key fingerprint: '+[string]$keyResult.owner_key_id) -ForegroundColor Yellow
53
+ $gesture=[ordered]@{schema='deadbyte.r193-owner-gesture.v1';status='APPROVED';
54
+ request_sha256=[string]$preview.request_sha256;review_phrase=$phrase;
55
+ approved_at_utc=[DateTime]::UtcNow.ToString('o')}
56
+ $gesturePath=Join-Path $owner ('gesture-'+[string]$preview.request_sha256+'.json')
57
+ $bytes=(New-Object Text.UTF8Encoding($false)).GetBytes(($gesture|ConvertTo-Json -Compress)+[Environment]::NewLine)
58
+ $stream=[IO.File]::Open($gesturePath,[IO.FileMode]::CreateNew,[IO.FileAccess]::Write,[IO.FileShare]::None)
59
+ try{$stream.Write($bytes,0,$bytes.Length);$stream.Flush($true)}finally{$stream.Dispose()}
60
+ $out=@(& $node $broker approve $request 2>&1) -join [Environment]::NewLine
61
+ if($LASTEXITCODE -ne 0){throw ('R193 signing blocked after protected enrollment: '+$out.Substring(0,[Math]::Min(500,$out.Length)))}
62
+ Write-Output $out
@@ -0,0 +1,49 @@
1
+ $ErrorActionPreference='Stop'
2
+ $root=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
3
+ $probe=Join-Path $root 'scripts\r193-limited-subject-probe.ps1'
4
+ $expectedSha='16317bffb0765e3856a6f64353ef728754e346636161cf2214ec0d0d3e5c7826'
5
+ if((Get-FileHash $probe).Hash.ToLowerInvariant() -cne $expectedSha){throw 'R193_PROBE_SCRIPT_CHANGED'}
6
+ $output=Join-Path $root 'R193-STANDARD-TOKEN-PROBE.json'
7
+ if(Test-Path $output){throw 'R193_EXISTING_OUTPUT - read before retest'}
8
+ $name='DEADBYTE-R193-Limited-Token-Diagnostic'
9
+ if(Get-ScheduledTask -TaskName $name -TaskPath '\' -ErrorAction SilentlyContinue){throw 'R193_TASK_ALREADY_EXISTS'}
10
+ $identity=[Security.Principal.WindowsIdentity]::GetCurrent()
11
+ $account=$identity.Name
12
+ $ps=Join-Path $env:WINDIR 'System32\WindowsPowerShell\v1.0\powershell.exe'
13
+ $arg='-NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "'+$probe+'"'
14
+ $action=New-ScheduledTaskAction -Execute $ps -Argument $arg -WorkingDirectory $root
15
+ $trigger=New-ScheduledTaskTrigger -Once -At ((Get-Date).AddDays(1))
16
+ $principal=New-ScheduledTaskPrincipal -UserId $account -LogonType Interactive -RunLevel Limited
17
+ $settings=New-ScheduledTaskSettingsSet -MultipleInstances IgnoreNew -ExecutionTimeLimit (New-TimeSpan -Minutes 1)
18
+ $registered=$false
19
+ try {
20
+ $null=Register-ScheduledTask -TaskName $name -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Description 'One-shot R193 native Windows token diagnostic. No grants.' -ErrorAction Stop
21
+ $registered=$true
22
+ $task=Get-ScheduledTask -TaskName $name -ErrorAction Stop
23
+ if([string]$task.Principal.RunLevel -ne 'Limited' -or [string]$task.Principal.LogonType -ne 'Interactive'){throw 'R193_TASK_NOT_LIMITED'}
24
+ Start-ScheduledTask -TaskName $name -ErrorAction Stop
25
+ $done=$false
26
+ for($i=0;$i -lt 28;$i++){
27
+ Start-Sleep -Milliseconds 700
28
+ if(Test-Path -LiteralPath $output -PathType Leaf){$done=$true;break}
29
+ }
30
+ if(-not $done){throw 'R193_LIMITED_TASK_NO_REPORT'}
31
+ $report=Get-Content -LiteralPath $output -Raw | ConvertFrom-Json
32
+ $info=Get-ScheduledTaskInfo -TaskName $name -ErrorAction Stop
33
+ $pass=($report.expected_standard -eq $true -and $report.process_report.elevated -eq $false -and $report.process_report.admin_enabled -eq $false -and $report.authority_granted -eq $false -and $info.LastTaskResult -eq 0)
34
+ [pscustomobject]@{
35
+ schema='deadbyte.r193-limited-token-scheduler-smoke.v1'
36
+ state=$(if($pass){'PASS'}else{'FAIL'})
37
+ limited_task=$name
38
+ scheduled_runlevel=[string]$task.Principal.RunLevel
39
+ native_subject=$report.process_report
40
+ task_exit=$info.LastTaskResult
41
+ source_sha256=$expectedSha
42
+ no_grant=$true
43
+ production_untouched=$true
44
+ }|ConvertTo-Json -Depth 8 -Compress
45
+ if(-not $pass){throw 'R193_EXPECTED_STANDARD_TOKEN_MISSING'}
46
+ } finally {
47
+ if($registered){Unregister-ScheduledTask -TaskName $name -TaskPath '\' -Confirm:$false -ErrorAction Stop}
48
+ }
49
+ if(Get-ScheduledTask -TaskName $name -TaskPath '\' -ErrorAction SilentlyContinue){throw 'R193_PROBE_TASK_NOT_REMOVED'}
@@ -0,0 +1,7 @@
1
+ $ErrorActionPreference='Stop'
2
+ $o=[ordered]@{schema='deadbyte.r193-toolchain.v1';toolchain=@{};disk_free_bytes=[int64](Get-PSDrive D).Free}
3
+ foreach($name in @('cl.exe','clang++.exe','g++.exe','cmake.exe','node.exe','powershell.exe')){
4
+ $q=Get-Command $name -ErrorAction SilentlyContinue
5
+ $o.toolchain[$name]=if($null -eq $q){'MISSING'}else{[string]$q.Source}
6
+ }
7
+ $o|ConvertTo-Json -Depth 4 -Compress
@@ -0,0 +1,21 @@
1
+ import {spawnSync} from 'node:child_process';
2
+ import {fileURLToPath} from 'node:url';
3
+ const root=fileURLToPath(new URL('..',import.meta.url));
4
+ const files=[
5
+ 'test/r188-owner-uac.test.mjs',
6
+ 'test/r188-uac-boundary.test.mjs',
7
+ 'test/r186-owner-grant-broker.test.mjs',
8
+ 'test/r193-uac-r70-bridge.test.mjs'
9
+ ];
10
+ const r=spawnSync(process.execPath,['--test','--test-concurrency=1',...files],{
11
+ cwd:root,encoding:'utf8',timeout:150000,maxBuffer:1024*1024,windowsHide:true,shell:false
12
+ });
13
+ const output=(r.stdout??'')+'\n'+(r.stderr??'');
14
+ const get=n=>{const m=[...output.matchAll(new RegExp('(?:^|\\n)[ℹ#]\\s*'+n+'\\s+(\\d+)','g'))];return m.length?Number(m.at(-1)[1]):null;};
15
+ const summary={tests:get('tests'),pass:get('pass'),fail:get('fail'),skipped:get('skipped')};
16
+ const pass=r.status===0&&summary.tests>=12&&summary.fail===0&&summary.pass===summary.tests-summary.skipped;
17
+ console.log(JSON.stringify({schema:'deadbyte.r193-uac-bridge-focused.v1',
18
+ status:pass?'PASS':'FAIL',exit:r.status,summary,files,
19
+ no_real_owner_enrollment:true,authority_granted:false,
20
+ production_untouched:true,tail:pass?null:output.slice(-12000)}));
21
+ if(!pass)process.exitCode=1;
@@ -0,0 +1,105 @@
1
+ // R188 - no Windows Hello, no PEM owner key, no grant issuance.
2
+ // Unprivileged challenge creation and read-only owner-review validation.
3
+ // Only an independently launched, R89-protected native elevated broker
4
+ // may record an actual approval. Do not turn this into a grant primitive.
5
+ import {createHash,randomBytes} from 'node:crypto';
6
+ import path from 'node:path';
7
+ import {canonicalJson} from './canonical-json.mjs';
8
+ const SHA=/^[a-f0-9]{64}$/;
9
+ const CHALLENGE=/^[A-Za-z0-9_-]{43}$/;
10
+ const ID=/^[A-Za-z0-9._-]{1,64}$/;
11
+ const digest=x=>createHash('sha256').update(Buffer.from(canonicalJson(x),'utf8')).digest('hex');
12
+ function invalid(msg){throw Error('R188 '+msg);}
13
+ function exact(value,fields,label){
14
+ if(!value||typeof value!=='object'||Array.isArray(value)||
15
+ Object.keys(value).length!==fields.length||
16
+ fields.some(f=>!Object.hasOwn(value,f)))invalid(label+' schema mismatch');
17
+ }
18
+ function project(p){
19
+ if(typeof p!=='string'||!path.win32.isAbsolute(p)||p.startsWith('\\\\')||
20
+ path.win32.normalize(p).toLowerCase()===path.win32.parse(p).root.toLowerCase())
21
+ invalid('project root must be a bounded local Windows path');
22
+ return path.win32.normalize(p);
23
+ }
24
+ function fields(o){
25
+ for(const k of ['machineEpoch','releaseManifestSha256','codingPolicySha256','autonomousPolicySha256']){
26
+ if(typeof o?.[k]!=='string'||!SHA.test(o[k]))invalid('invalid '+k);
27
+ }
28
+ if(o.rootId!=='core'||!ID.test(o.rootId))invalid('root scope must be core');
29
+ const root=project(o.projectRoot);
30
+ if(!Number.isSafeInteger(o.maxSeconds)||o.maxSeconds<1||o.maxSeconds>3600)
31
+ invalid('maxSeconds outside owner-reviewed window');
32
+ return root;
33
+ }
34
+ const scopeKeys=['schema','machine_epoch','release_manifest_sha256',
35
+ 'coding_policy_sha256','autonomous_policy_sha256','root_id','project_root',
36
+ 'operation','max_seconds','issued_at_utc','expires_at_utc'];
37
+ const requestKeys=['schema','challenge','subject','request_sha256','review_phrase',
38
+ 'owner_approved','authority_granted','require_interactive_uac'];
39
+ function iso(v){
40
+ if(typeof v!=='string'||!/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z$/.test(v)||
41
+ !Number.isFinite(Date.parse(v))||new Date(v).toISOString()!==v)
42
+ invalid('UTC time not canonical');
43
+ return Date.parse(v);
44
+ }
45
+ function hashFor(challenge,subject){return digest({schema:'deadbyte.r188-owner-uac-request.v1',challenge,subject});}
46
+ function phrase(hash){return 'APPROVE-'+hash.slice(0,12).toUpperCase();}
47
+ export function createR188OwnerUacRequest({
48
+ machineEpoch,releaseManifestSha256,codingPolicySha256,autonomousPolicySha256,
49
+ rootId,projectRoot,maxSeconds,now=new Date(),expiresInMs=120000
50
+ }={}){
51
+ const input={machineEpoch,releaseManifestSha256,codingPolicySha256,
52
+ autonomousPolicySha256,rootId,projectRoot,maxSeconds};
53
+ const normalized=fields(input);
54
+ if(!(now instanceof Date)||!Number.isFinite(now.getTime())||
55
+ !Number.isSafeInteger(expiresInMs)||expiresInMs<1000||expiresInMs>300000)
56
+ invalid('request lifetime invalid');
57
+ const subject=Object.freeze({
58
+ schema:'deadbyte.r188-owner-uac-subject.v1',machine_epoch:machineEpoch,
59
+ release_manifest_sha256:releaseManifestSha256,
60
+ coding_policy_sha256:codingPolicySha256,
61
+ autonomous_policy_sha256:autonomousPolicySha256,
62
+ root_id:rootId,project_root:normalized,
63
+ operation:'autonomous_goal_run',max_seconds:maxSeconds,
64
+ issued_at_utc:now.toISOString(),
65
+ expires_at_utc:new Date(now.getTime()+expiresInMs).toISOString()
66
+ });
67
+ const challenge=randomBytes(32).toString('base64url');
68
+ const request_sha256=hashFor(challenge,subject);
69
+ return Object.freeze({schema:'deadbyte.r188-owner-uac-request.v1',
70
+ challenge,subject,request_sha256,review_phrase:phrase(request_sha256),
71
+ owner_approved:false,authority_granted:false,require_interactive_uac:true});
72
+ }
73
+ export function verifyR188OwnerUacRequest({request,expected,now=new Date()}={}){
74
+ exact(request,requestKeys,'request');exact(request.subject,scopeKeys,'subject');
75
+ const subject=request.subject;
76
+ const root=fields(expected);
77
+ if(request.schema!=='deadbyte.r188-owner-uac-request.v1'||
78
+ subject.schema!=='deadbyte.r188-owner-uac-subject.v1'||
79
+ request.owner_approved!==false||request.authority_granted!==false||
80
+ request.require_interactive_uac!==true||
81
+ typeof request.challenge!=='string'||!CHALLENGE.test(request.challenge)||
82
+ Buffer.from(request.challenge,'base64url').length!==32||
83
+ Buffer.from(request.challenge,'base64url').toString('base64url')!==request.challenge)
84
+ invalid('request shape or challenge invalid');
85
+ const expectedBindings={
86
+ machine_epoch:expected.machineEpoch,release_manifest_sha256:expected.releaseManifestSha256,
87
+ coding_policy_sha256:expected.codingPolicySha256,
88
+ autonomous_policy_sha256:expected.autonomousPolicySha256,root_id:expected.rootId,
89
+ project_root:root,operation:'autonomous_goal_run',max_seconds:expected.maxSeconds
90
+ };
91
+ for(const [k,v] of Object.entries(expectedBindings)){
92
+ if(subject[k]!==v)invalid('request scope mismatch: '+k);
93
+ }
94
+ if(!(now instanceof Date)||!Number.isFinite(now.getTime()))invalid('current time invalid');
95
+ const issued=iso(subject.issued_at_utc),expires=iso(subject.expires_at_utc);
96
+ if(expires<=issued||expires-issued>300000||
97
+ now.getTime()<issued||now.getTime()>=expires)invalid('request expired or not yet valid');
98
+ if(typeof request.request_sha256!=='string'||!SHA.test(request.request_sha256)||
99
+ request.request_sha256!==hashFor(request.challenge,subject)||
100
+ request.review_phrase!==phrase(request.request_sha256))
101
+ invalid('request digest or owner phrase altered');
102
+ return Object.freeze({status:'VERIFIED_FOR_REVIEW_ONLY',request_sha256:request.request_sha256,
103
+ review_phrase:request.review_phrase,authority_granted:false,owner_approved:false,
104
+ next_gate:'PROTECTED_INTERACTIVE_UAC_WITH_EXACT_REQUEST_AND_EPOCH'});
105
+ }
@@ -0,0 +1,21 @@
1
+ // R188: pure fail-closed decision gate, NOT proof of a Windows UAC action.
2
+ // A privileged native broker MUST determine these facts independently using
3
+ // token and ACL inspection. Never accept a caller's self-reported booleans.
4
+ export function assessR188UacBoundary(e={}){
5
+ const finish=(reason)=>Object.freeze({schema:'deadbyte.r188-uac-boundary.v1',
6
+ status:'BLOCKED',reason,authority_granted:false,grant_issued:false});
7
+ if(e.codingElevation!=='standard')return finish('CODING_ALREADY_ELEVATED');
8
+ if(e.privilegedParentReachable!==false)return finish('ELEVATED_PARENT_STILL_REACHABLE');
9
+ if(e.ownerElevation!=='elevated')return finish('OWNER_NOT_ELEVATED');
10
+ if(e.protectedBroker!==true)return finish('BROKER_NOT_PROTECTED');
11
+ if(e.enableUac!==true||e.secureDesktop!==true||
12
+ e.promptMode!=='explicit_secure_desktop')
13
+ return finish('UAC_NOT_INTERACTIVE_AND_SECURE');
14
+ if(e.nativeEpochPinned!==true||e.releaseAndPoliciesPinned!==true)
15
+ return finish('AUTHORITY_EPOCH_OR_POLICY_NOT_PINNED');
16
+ if(e.ownerGesture!=='approved')return finish('OWNER_NOT_APPROVED');
17
+ return Object.freeze({schema:'deadbyte.r188-uac-boundary.v1',
18
+ status:'ELIGIBLE_FOR_PROTECTED_OWNER_REVIEW',reason:null,
19
+ authority_granted:false,grant_issued:false,
20
+ next_gate:'SIGNED_EPOCH_ONE_TIME_GRANT_TRANSACTION'});
21
+ }