deadbyte-mcp 0.15.43 → 0.15.44

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 (129) hide show
  1. package/MANIFEST.SHA256 +128 -67
  2. package/PROVENANCE.json +23 -12
  3. package/README.txt +18 -18
  4. package/RELEASE.json +28 -14
  5. package/SBOM.cdx.json +14 -2
  6. package/TEST-MATRIX.json +41 -10
  7. package/bin/appcontainer-stage.obj +0 -0
  8. package/bin/bootstrap-advapi32.obj +0 -0
  9. package/bin/bootstrap-exitcode.obj +0 -0
  10. package/bin/bootstrap-kernel32.obj +0 -0
  11. package/bin/child-control-probe.obj +0 -0
  12. package/bin/child-control-stage.obj +0 -0
  13. package/bin/contained-reverse-worker.obj +0 -0
  14. package/bin/contained-transform-worker.obj +0 -0
  15. package/bin/containment-probe.obj +0 -0
  16. package/bin/deadbyte-contain.obj +0 -0
  17. package/bin/deadbyte-desktop-input-r40.obj +0 -0
  18. package/bin/deadbyte-desktop-observer-r40.obj +0 -0
  19. package/bin/deadbyte-desktop-uia-r40.obj +0 -0
  20. package/bin/deadbyte-exec.obj +0 -0
  21. package/bin/deadbyte-hardware-observer-r45.obj +0 -0
  22. package/bin/deadbyte-native-inspect-r67.exe +0 -0
  23. package/bin/deadbyte-native-inspect-r67.obj +0 -0
  24. package/bin/deadbyte-process-host.obj +0 -0
  25. package/bin/deadbyte-tunnel-host.obj +0 -0
  26. package/bridge/package.json +1 -1
  27. package/controller/deadbyte-desktop-policy.json +5 -5
  28. package/controller/deadbyte-process-policy.json +4 -4
  29. package/docs/R67-ALPHA-REFERENCE-DIFFERENTIAL.md +42 -0
  30. package/docs/R67-ALPHA-STATIC-COMPARISON.json +205 -0
  31. package/docs/R67-CANDIDATE-PARENT.json +10 -0
  32. package/docs/R67-EVIDENCE-RECONCILE-CLOSEOUT-20261011.md +64 -0
  33. package/docs/R67-FULL-REGRESSION-UNKNOWN.json +27 -0
  34. package/docs/R67-NATIVE-INSPECT-BINARY.json +11 -0
  35. package/docs/R67-NPM-EXDEV-PRESERVATION-20261011.md +39 -0
  36. package/docs/R67-OBSERVATION-TRUTH.md +82 -0
  37. package/docs/R67-REFERENCE-GAP-MATRIX.json +57 -0
  38. package/docs/R67-REGRESSION-CLOSURE-20261011.md +24 -0
  39. package/native/deadbyte-native-inspect-r67.cpp +252 -0
  40. package/package.json +6 -3
  41. package/proof/CONTAINMENT-BUILD.txt +6 -6
  42. package/scripts/build-native-inspector-r67.ps1 +28 -0
  43. package/scripts/gate-windows-r67.ps1 +56 -0
  44. package/scripts/npm-preserve-artifact-r67.mjs +99 -0
  45. package/scripts/npm-release-r48.mjs +10 -2
  46. package/scripts/npm-release-readiness-r67.mjs +26 -0
  47. package/scripts/r67-acquire-alpha-reference.mjs +95 -0
  48. package/scripts/r67-audit-nonpass-source.mjs +39 -0
  49. package/scripts/r67-compare-desktop-alpha.mjs +48 -0
  50. package/scripts/r67-diagnose-failed-shard.mjs +23 -0
  51. package/scripts/r67-durable-batch.mjs +42 -0
  52. package/scripts/r67-focused-gate.mjs +58 -0
  53. package/scripts/r67-full-regression.mjs +28 -0
  54. package/scripts/r67-independent-observation-verify.mjs +36 -0
  55. package/scripts/r67-independent-runtime-observation-verify.mjs +63 -0
  56. package/scripts/r67-nonpass-adjudicate.mjs +20 -0
  57. package/scripts/r67-publish-boundary-audit.mjs +32 -0
  58. package/scripts/r67-regression-reconcile.mjs +10 -0
  59. package/scripts/r67-regression-shard-run.mjs +70 -0
  60. package/scripts/r67-run-shard-batch.mjs +18 -0
  61. package/scripts/r67-stage-candidate.mjs +30 -0
  62. package/scripts/r67-verify-parent-ping.mjs +22 -0
  63. package/scripts/release-manifest.mjs +1 -0
  64. package/src/activation-continuity-engine-r65.mjs +2 -1
  65. package/src/autonomous-runtime.mjs +1 -1
  66. package/src/deadbyte-cli.mjs +33 -1
  67. package/src/machine-fs-smoke-client.mjs +13 -5
  68. package/src/machine-identity.mjs +59 -2
  69. package/src/machine-mcp-tools.mjs +8 -0
  70. package/src/mcp-server.mjs +11 -2
  71. package/src/native-inspector-r67.mjs +66 -0
  72. package/src/r67-diagnostic-export.mjs +118 -0
  73. package/src/r67-diagnostics-verify.mjs +82 -0
  74. package/src/r67-evidence-reconcile.mjs +128 -0
  75. package/src/r67-native-observation-authority.mjs +45 -0
  76. package/src/r67-observation-receipt.mjs +43 -0
  77. package/src/r67-regression-shards.mjs +176 -0
  78. package/src/remote-live-log.mjs +14 -10
  79. package/src/tool-audit.mjs +1 -1
  80. package/src/version.mjs +1 -1
  81. package/test/agent-runtime.test.mjs +1 -1
  82. package/test/autonomous-loop.test.mjs +11 -6
  83. package/test/autonomous-runtime.test.mjs +1 -1
  84. package/test/coding-plane.test.mjs +1 -1
  85. package/test/full-max-catalog-r46.test.mjs +1 -1
  86. package/test/output-schema.test.mjs +1 -1
  87. package/test/r51-live-log-polling.test.mjs +12 -0
  88. package/test/r53-release-contract.test.mjs +1 -1
  89. package/test/r54-release-contract.test.mjs +1 -1
  90. package/test/r55-release-contract.test.mjs +1 -1
  91. package/test/r56-release-contract.test.mjs +1 -1
  92. package/test/r57-release-contract.test.mjs +1 -1
  93. package/test/r58-bundled-bridge.test.mjs +1 -1
  94. package/test/r58-release-contract.test.mjs +2 -2
  95. package/test/r58-windows-gate.test.mjs +1 -1
  96. package/test/r59-tool-surface-compat.test.mjs +1 -1
  97. package/test/r60-release-contract.test.mjs +3 -3
  98. package/test/r61-release-contract.test.mjs +1 -1
  99. package/test/r62-release-contract.test.mjs +1 -1
  100. package/test/r63-release-contract.test.mjs +1 -1
  101. package/test/r64-release-contract.test.mjs +1 -1
  102. package/test/r65-epoch-native-activation-integration.test.mjs +4 -4
  103. package/test/r65-release-contract.test.mjs +1 -1
  104. package/test/r66-release-contract.test.mjs +2 -1
  105. package/test/r67-cli-integration.test.mjs +41 -0
  106. package/test/r67-diagnostics-cli.test.mjs +60 -0
  107. package/test/r67-diagnostics-verify.test.mjs +49 -0
  108. package/test/r67-diagnostics-zip-oracle.test.mjs +38 -0
  109. package/test/r67-diagnostics.test.mjs +60 -0
  110. package/test/r67-evidence-reconcile.test.mjs +186 -0
  111. package/test/r67-isolated-slot-rollback-restore.test.mjs +62 -0
  112. package/test/r67-live-log-secret-canary.test.mjs +44 -0
  113. package/test/r67-machine-fs-smoke-epoch.test.mjs +22 -0
  114. package/test/r67-native-inspector.test.mjs +131 -0
  115. package/test/r67-native-observation-authority.test.mjs +49 -0
  116. package/test/r67-npm-cross-volume.test.mjs +74 -0
  117. package/test/r67-npm-publish-gate.test.mjs +38 -0
  118. package/test/r67-regression-shards.test.mjs +184 -0
  119. package/test/r67-release-contract.test.mjs +44 -0
  120. package/test/r67-runtime-observation-binding.test.mjs +86 -0
  121. package/test/r67-server-observation-wiring.test.mjs +12 -0
  122. package/test/r67-signed-receipt.test.mjs +66 -0
  123. package/test/r67-skip-rationale.test.mjs +31 -0
  124. package/test/r67-tool-annotations.test.mjs +21 -0
  125. package/test/r67-windows-gate-argv.test.mjs +13 -0
  126. package/test/release-version.test.mjs +1 -1
  127. package/test/remote-live-log-r36.test.mjs +10 -0
  128. package/test/remote-live-log-r37.test.mjs +29 -0
  129. package/test/semantic-multilang.test.mjs +1 -1
@@ -20,6 +20,7 @@ import { recoverInterruptedSlotUpdates } from './runtime-update.mjs';
20
20
  import { decodeUtf8Strict } from './text-policy.mjs';
21
21
  import { assertHostArmed, hostExec, hostExecInline, hostExecNative, hostFileRead, hostFileWrite, loadHostPolicy } from './host-plane.mjs';
22
22
  import { createMachineRuntime } from './machine-identity.mjs';
23
+ import { createR67NativeObservationAuthority } from './r67-native-observation-authority.mjs';
23
24
  import { registerMachineTools } from './machine-mcp-tools.mjs';
24
25
  import { createAgentRuntime } from './agent-runtime.mjs';
25
26
  import { registerAgentTools } from './agent-mcp-tools.mjs';
@@ -107,10 +108,19 @@ if (!privilegedPolicyExplicit) {
107
108
  }
108
109
  planeRegistry.define('host',{configured:Boolean(privilegedPolicyPath),required:false});
109
110
  const hostPolicy=await planeRegistry.initialize('host',async()=>loadHostPolicy(privilegedPolicyPath));
111
+ // The machine runtime is initialized before Coding. Authority is resolved lazily
112
+ // from the trusted Coding plane at the moment of each observation and rechecked
113
+ // after the native read, never from a client-supplied permission object.
114
+ let codingPolicy=null;
115
+ const nativeObserveMode=process.env.DEADBYTE_R67_NATIVE_OBSERVE ?? '0';
116
+ if(!['0','1'].includes(nativeObserveMode))throw new Error('DEADBYTE_R67_NATIVE_OBSERVE must be 0 or 1');
117
+ const assertNativeObservationAuthority=createR67NativeObservationAuthority({
118
+ getCodingPolicy:()=>codingPolicy,enabled:nativeObserveMode==='1'
119
+ });
110
120
  const machineRuntimeMode = process.env.DEADBYTE_MACHINE_RUNTIME ?? '0';
111
121
  if (!['0', '1'].includes(machineRuntimeMode)) throw new Error('DEADBYTE_MACHINE_RUNTIME must be 0 or 1');
112
122
  planeRegistry.define('machine',{configured:machineRuntimeMode==='1',required:true});
113
- const machineRuntime=await planeRegistry.initialize('machine',async()=>createMachineRuntime({stateRoot:runtimeStateRoot}));
123
+ const machineRuntime=await planeRegistry.initialize('machine',async()=>createMachineRuntime({stateRoot:runtimeStateRoot,assertObservationAuthority:assertNativeObservationAuthority}));
114
124
  const agentRuntimeMode = process.env.DEADBYTE_AGENT_RUNTIME ?? '0';
115
125
  if (!['0', '1'].includes(agentRuntimeMode)) throw new Error('DEADBYTE_AGENT_RUNTIME must be 0 or 1');
116
126
  planeRegistry.define('agent',{configured:agentRuntimeMode==='1',required:false});
@@ -142,7 +152,6 @@ if (codingRuntimeMode === '1' && !codingPolicyPath) {
142
152
  catch (error) { if (error?.code !== 'ENOENT') throw error; }
143
153
  }
144
154
  planeRegistry.define('coding',{configured:codingRuntimeMode==='1',required:false});
145
- let codingPolicy=null;
146
155
  const codingRuntime=await planeRegistry.initialize('coding',async()=>{
147
156
  if(!codingPolicyPath) throw new Error('DEADBYTE_CODING_RUNTIME=1 requires a coding policy');
148
157
  codingPolicy=await loadCodingPolicy(codingPolicyPath);
@@ -0,0 +1,66 @@
1
+ import {spawnSync} from 'node:child_process';
2
+ import {createHash} from 'node:crypto';
3
+ import {lstat,readFile} from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import {fileURLToPath} from 'node:url';
6
+ import {signR67Observation} from './r67-observation-receipt.mjs';
7
+
8
+ const root=path.dirname(path.dirname(fileURLToPath(import.meta.url)));
9
+ const exe=path.join(root,'bin','deadbyte-native-inspect-r67.exe');
10
+ const metaFile=path.join(root,'docs','R67-NATIVE-INSPECT-BINARY.json');
11
+ const hash=b=>createHash('sha256').update(b).digest('hex');
12
+ const validLimit=(s,min,max)=>{if(!/^[1-9][0-9]*$/.test(s))throw new Error('invalid positive limit');const n=Number(s);if(!Number.isSafeInteger(n)||n<min||n>max)throw new Error('limit out of range');return String(n);};
13
+ export function nativeInspectArgs(rest){
14
+ const [kind,...args]=rest;
15
+ if(kind==='process'){if(args.length>1)throw new Error('inspect process [1..256]');return ['process',...(args.length?[validLimit(args[0],1,256)]:[])];}
16
+ if(kind==='identity'){
17
+ if(args.length!==1)throw new Error('inspect identity <PID>');
18
+ return ['identity',validLimit(args[0],1,4294967295)];
19
+ }
20
+ if(kind==='memory'){
21
+ if(args[0]==='self'){
22
+ if(args.length>2)throw new Error('inspect memory self [limit]');
23
+ return ['map','self',...(args.length===2?[validLimit(args[1],1,512)]:[])];
24
+ }
25
+ if(args.length<2||args.length>3)throw new Error('inspect memory PID <creation_filetime> [limit]');
26
+ const pid=validLimit(args[0],1,4294967295);
27
+ const token=args[1];
28
+ if(!/^[1-9][0-9]*$/.test(token)||BigInt(token)>18446744073709551615n)throw new Error('invalid process creation FILETIME');
29
+ return ['map',pid,token,...(args.length===3?[validLimit(args[2],1,512)]:[])];
30
+ }
31
+ if(kind==='pe'){
32
+ if(args.length!==1||!args[0]||args[0].includes('\0'))throw new Error('inspect pe <file>');
33
+ return ['pe',path.resolve(args[0])];
34
+ }
35
+ throw new Error('inspect expects process, memory, or pe');
36
+ }
37
+ export async function runNativeInspect(rest,{trustedSigner=null}={}){
38
+ if(process.platform!=='win32')throw new Error('native inspector requires win32');
39
+ const args=nativeInspectArgs(rest);
40
+ const meta=JSON.parse(await readFile(metaFile,'utf8'));
41
+ if(meta?.schema!=='deadbyte.r67-native-inspector-binary.v1'||meta.exe!=='bin/deadbyte-native-inspect-r67.exe'||!/^[a-f0-9]{64}$/.test(meta.sha256))throw new Error('R67 native executable authority invalid');
42
+ const info=await lstat(exe);
43
+ if(!info.isFile()||info.isSymbolicLink())throw new Error('R67 executable is not a regular non-symlink');
44
+ const before=hash(await readFile(exe));
45
+ if(before!==meta.sha256)throw new Error('R67 executable hash pin mismatch');
46
+ const result=spawnSync(exe,args,{encoding:'utf8',windowsHide:true,shell:false,timeout:15000,maxBuffer:2097152});
47
+ const after=hash(await readFile(exe));
48
+ if(after!==before)throw new Error('R67 executable drift after execution; outcome uncertain');
49
+ if(result.error)throw new Error('native inspector execution failed: '+result.error.message);
50
+ const stdout=String(result.stdout||'');
51
+ if(Buffer.byteLength(stdout,'utf8')>2097152)throw new Error('native inspector output exceeded limit');
52
+ let parsed;try{parsed=JSON.parse(stdout);}catch{throw new Error('native inspector output invalid JSON');}
53
+ if(parsed?.schema!=='deadbyte.native-inspect.r67.v1')throw new Error('native inspector output schema mismatch');
54
+ if(parsed.status==='ok'){
55
+ if(result.status!==0||parsed.operation!==args[0]||!parsed.data||parsed.data_sha256!==hash(Buffer.from(JSON.stringify(parsed.data),'utf8')))throw new Error('native inspector result digest mismatch');
56
+ }else if(parsed.status!=='failed'||result.status!==2||typeof parsed.error!=='string')throw new Error('native inspector failure contract mismatch');
57
+ if(trustedSigner!==null){
58
+ if(!trustedSigner||!trustedSigner.privateKey||!trustedSigner.publicKey)throw new Error('R67 signed observation requires an explicit trusted signer');
59
+ const receipt=signR67Observation({
60
+ ...trustedSigner,operation:args[0],requestSha256:hash(Buffer.from(JSON.stringify(args),'utf8')),
61
+ executableSha256:before,result:parsed
62
+ });
63
+ return {result:parsed,receipt};
64
+ }
65
+ return parsed;
66
+ }
@@ -0,0 +1,118 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {lstat,readFile,readdir,open} from 'node:fs/promises';
3
+ import path from 'node:path';
4
+
5
+ const hash=bytes=>createHash('sha256').update(bytes).digest('hex');
6
+ const allowedLog=/^controller-(?:start|restart)\.(?:stdout|stderr)\.log$/;
7
+ const releasePattern=/^v[0-9]+\.[0-9]+\.[0-9]+-[a-f0-9]{16}$/;
8
+ const hex64=/^[a-f0-9]{64}$/;
9
+ const events=['reconnect','connected','disconnect','timeout','cancel','rollback','restore','revoked','ready','start','restart','failed','success'];
10
+ const EVENT_RX=new RegExp('\\b('+events.join('|')+')\\b','i');
11
+ const timestampRx=/^(\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z)\b/;
12
+
13
+ export function redactDiagnosticLine(text){
14
+ if(typeof text!=='string'||text.length>8192)return null;
15
+ const level=/\b(ERROR|WARN|INFO|DEBUG)\b/i.exec(text)?.[1]?.toUpperCase();
16
+ const event=EVENT_RX.exec(text)?.[1]?.toLowerCase();
17
+ if(!level||!event)return null;
18
+ const result={};
19
+ const stamp=timestampRx.exec(text)?.[1];
20
+ if(stamp&&!Number.isNaN(Date.parse(stamp)))result.timestamp=stamp;
21
+ result.level=level;result.event=event;
22
+ const error=/\bwin32=(\d{1,5})\b/i.exec(text)?.[1];
23
+ if(error!==undefined&&Number(error)<=65535)result.win32_error=Number(error);
24
+ return result;
25
+ }
26
+ function crc32(data){
27
+ let crc=0xffffffff;
28
+ for(const value of data){
29
+ crc^=value;
30
+ for(let i=0;i<8;i++)crc=(crc>>>1)^((crc&1)?0xedb88320:0);
31
+ }
32
+ return (crc^0xffffffff)>>>0;
33
+ }
34
+ function zipStore(entries){
35
+ const locals=[],centrals=[];
36
+ let offset=0;
37
+ for(const [name,contents] of entries){
38
+ if(!/^[a-z0-9.-]+\.json$/.test(name))throw new Error('noncanonical archive entry');
39
+ const nameBytes=Buffer.from(name),data=Buffer.from(contents,'utf8'),crc=crc32(data);
40
+ if(data.length>1024*1024)throw new Error('archive payload too large');
41
+ const local=Buffer.alloc(30);
42
+ local.writeUInt32LE(0x04034b50,0);
43
+ local.writeUInt16LE(20,4);
44
+ local.writeUInt32LE(crc,14);
45
+ local.writeUInt32LE(data.length,18);local.writeUInt32LE(data.length,22);
46
+ local.writeUInt16LE(nameBytes.length,26);
47
+ locals.push(local,nameBytes,data);
48
+ const central=Buffer.alloc(46);
49
+ central.writeUInt32LE(0x02014b50,0);
50
+ central.writeUInt16LE(20,4);central.writeUInt16LE(20,6);
51
+ central.writeUInt32LE(crc,16);
52
+ central.writeUInt32LE(data.length,20);central.writeUInt32LE(data.length,24);
53
+ central.writeUInt16LE(nameBytes.length,28);
54
+ central.writeUInt32LE(offset,42);
55
+ centrals.push(central,nameBytes);
56
+ offset+=local.length+nameBytes.length+data.length;
57
+ }
58
+ const directory=Buffer.concat(centrals);
59
+ const end=Buffer.alloc(22);
60
+ end.writeUInt32LE(0x06054b50,0);
61
+ end.writeUInt16LE(entries.length,8);end.writeUInt16LE(entries.length,10);
62
+ end.writeUInt32LE(directory.length,12);end.writeUInt32LE(offset,16);
63
+ return Buffer.concat([...locals,directory,end]);
64
+ }
65
+ export function makeOfflineDiagnosticBundle({releaseId,manifestSha256,logs=[]}={}){
66
+ if(!releasePattern.test(releaseId??'')||!hex64.test(manifestSha256??''))throw new Error('trusted release identity invalid');
67
+ if(!Array.isArray(logs)||logs.length>8)throw new Error('log source budget exceeded');
68
+ const redacted=[];
69
+ const sources=new Set();
70
+ for(const source of logs){
71
+ if(!source||!allowedLog.test(source.source)||typeof source.content!=='string'||Buffer.byteLength(source.content)>65536||sources.has(source.source))
72
+ throw new Error('unsupported diagnostic source');
73
+ sources.add(source.source);
74
+ const lines=source.content.split(/\r?\n/).slice(0,512);
75
+ for(const line of lines){
76
+ if(redacted.length===256)break;
77
+ const record=redactDiagnosticLine(line);
78
+ if(record)redacted.push({source:source.source,...record});
79
+ }
80
+ }
81
+ const summary={schema:'deadbyte.r67-offline-diagnostics.v1',release_id:releaseId,release_manifest_sha256:manifestSha256,
82
+ network_upload:'NEVER',redaction:'FIXED_FIELDS_ONLY',source_count:sources.size,redacted_event_count:redacted.length,
83
+ raw_log_lines_exported:0,private_memory_exported:false};
84
+ const zip=zipStore([
85
+ ['diagnostics.json',JSON.stringify(summary,null,2)+'\n'],
86
+ ['redacted-events.json',JSON.stringify(redacted,null,2)+'\n']
87
+ ]);
88
+ return {zip,summary,archive_sha256:hash(zip)};
89
+ }
90
+ async function regularBounded(file,maxBytes){
91
+ const info=await lstat(file);
92
+ if(!info.isFile()||info.isSymbolicLink()||info.size>maxBytes)throw new Error('invalid or oversized diagnostic source');
93
+ const b=await readFile(file);
94
+ if(b.length>maxBytes)throw new Error('source size changed');
95
+ return b.toString('utf8');
96
+ }
97
+ export async function exportOfflineDiagnostics({stateRoot,outputPath,upload=false}={}){
98
+ if(upload!==false)throw new Error('network upload disabled unconditionally');
99
+ if(typeof outputPath!=='string'||!outputPath||/^[a-z]+:\/\//i.test(outputPath))throw new Error('explicit local outputPath required');
100
+ if(typeof stateRoot!=='string'||!stateRoot)throw new Error('local stateRoot required');
101
+ const root=path.resolve(stateRoot);
102
+ const pointer=JSON.parse(await regularBounded(path.join(root,'active-release.json'),131072));
103
+ const logDir=path.join(root,'runtime','logs');
104
+ let names=[];
105
+ try{names=(await readdir(logDir)).filter(n=>allowedLog.test(n)).sort().slice(0,8);}catch(error){if(error.code!=='ENOENT')throw error;}
106
+ const logs=[];
107
+ for(const name of names){
108
+ const file=path.join(logDir,name);
109
+ try{logs.push({source:name,content:await regularBounded(file,65536)});}
110
+ catch(error){if(error.code!=='ENOENT')throw error;}
111
+ }
112
+ const bundle=makeOfflineDiagnosticBundle({releaseId:pointer.release_id,manifestSha256:pointer.manifest_sha256,logs});
113
+ const target=path.resolve(outputPath);
114
+ const h=await open(target,'wx',0o600);
115
+ try{await h.writeFile(bundle.zip);await h.sync();}finally{await h.close();}
116
+ return {status:'written_local_only',uploaded:false,archive_sha256:bundle.archive_sha256,bytes:bundle.zip.length,
117
+ source_count:bundle.summary.source_count,redacted_event_count:bundle.summary.redacted_event_count};
118
+ }
@@ -0,0 +1,82 @@
1
+ import {createHash} from 'node:crypto';
2
+ const sha=b=>createHash('sha256').update(b).digest('hex');
3
+ const MAX=4*1024*1024;
4
+ function crc32(bytes){
5
+ let crc=0xffffffff;
6
+ for(const value of bytes){crc^=value;for(let i=0;i<8;i++)crc=(crc>>>1)^((crc&1)?0xedb88320:0);}
7
+ return (crc^0xffffffff)>>>0;
8
+ }
9
+ function fail(what){throw new Error('ZIP integrity: '+what);}
10
+ function read16(b,o){if(o<0||o+2>b.length)fail('boundary');return b.readUInt16LE(o);}
11
+ function read32(b,o){if(o<0||o+4>b.length)fail('boundary');return b.readUInt32LE(o);}
12
+ export function verifyOfflineDiagnosticsZip(input){
13
+ if(!Buffer.isBuffer(input))throw new Error('ZIP input must be Buffer');
14
+ const b=input;
15
+ if(b.length<22||b.length>MAX)throw new Error('ZIP too large or truncated size');
16
+ const end=b.length-22;
17
+ if(read32(b,end)!==0x06054b50)fail('missing terminal EOCD or trailing data');
18
+ if(read16(b,end+4)||read16(b,end+6)||read16(b,end+20))fail('multidisk/comments forbidden');
19
+ const count=read16(b,end+10);
20
+ if(count!==2||read16(b,end+8)!==2)fail('exactly two entries required');
21
+ const centralSize=read32(b,end+12),centralOffset=read32(b,end+16);
22
+ if(centralOffset+centralSize!==end)fail('central directory boundary invalid');
23
+ const expected=['diagnostics.json','redacted-events.json'];
24
+ let position=centralOffset;
25
+ let localEnd=0;
26
+ const files={};
27
+ for(let i=0;i<2;i++){
28
+ if(read32(b,position)!==0x02014b50)fail('bad central file header');
29
+ if(read16(b,position+8)||read16(b,position+10))fail('unsafe ZIP flags or compressed method');
30
+ const crc=read32(b,position+16),stored=read32(b,position+20),raw=read32(b,position+24);
31
+ const n=read16(b,position+28),extra=read16(b,position+30),comment=read16(b,position+32);
32
+ const off=read32(b,position+42);
33
+ if(stored!==raw||stored>1048576||extra||comment||read16(b,position+34))fail('unsupported entry');
34
+ if(position+46+n>centralOffset+centralSize)fail('central filename boundary');
35
+ const name=b.toString('utf8',position+46,position+46+n);
36
+ if(name!==expected[i])fail('unexpected entry name/order');
37
+ if(read32(b,off)!==0x04034b50||read16(b,off+6)||read16(b,off+8))fail('local header unsafe flags');
38
+ if(read32(b,off+14)!==crc||read32(b,off+18)!==stored||read32(b,off+22)!==raw)fail('local versus central mismatch');
39
+ const ln=read16(b,off+26),le=read16(b,off+28);
40
+ if(ln!==n||le!==0||b.toString('utf8',off+30,off+30+ln)!==name)fail('local filename mismatch');
41
+ const start=off+30+n,endByte=start+stored;
42
+ if(endByte>centralOffset||off!==localEnd)fail('local file bounds or gap');
43
+ const data=b.subarray(start,endByte);
44
+ if(crc32(data)!==crc)fail('CRC mismatch');
45
+ files[name]=data;
46
+ localEnd=endByte;
47
+ position+=46+n;
48
+ }
49
+ if(position!==centralOffset+centralSize||localEnd!==centralOffset)fail('file/directory overlap or padding');
50
+ let summary,events;
51
+ try{
52
+ summary=JSON.parse(files['diagnostics.json'].toString('utf8'));
53
+ events=JSON.parse(files['redacted-events.json'].toString('utf8'));
54
+ }catch{fail('invalid JSON');}
55
+ if(!summary||typeof summary!=='object'||Array.isArray(summary)||
56
+ summary.schema!=='deadbyte.r67-offline-diagnostics.v1'||
57
+ !/^v\d+\.\d+\.\d+-[a-f0-9]{16}$/.test(summary.release_id)||
58
+ !/^[a-f0-9]{64}$/.test(summary.release_manifest_sha256)||
59
+ summary.redaction!=='FIXED_FIELDS_ONLY'||summary.network_upload!=='NEVER'||
60
+ summary.raw_log_lines_exported!==0||summary.private_memory_exported!==false||
61
+ !Number.isInteger(summary.source_count)||summary.source_count<0||summary.source_count>8||
62
+ !Number.isInteger(summary.redacted_event_count)||summary.redacted_event_count<0||summary.redacted_event_count>256)
63
+ fail('unsafe diagnostic summary');
64
+ const allowedSummary=['schema','release_id','release_manifest_sha256','network_upload','redaction','source_count','redacted_event_count','raw_log_lines_exported','private_memory_exported'];
65
+ if(Object.keys(summary).sort().join('|')!==allowedSummary.sort().join('|'))fail('unexpected summary fields');
66
+ if(!Array.isArray(events)||events.length!==summary.redacted_event_count)fail('event count mismatch');
67
+ const sources=new Set();
68
+ const validLevels=new Set(['ERROR','WARN','INFO','DEBUG']);
69
+ const validEvents=new Set(['reconnect','connected','disconnect','timeout','cancel','rollback','restore','revoked','ready','start','restart','failed','success']);
70
+ for(const event of events){
71
+ if(!event||typeof event!=='object'||Array.isArray(event))fail('malformed event');
72
+ const keys=Object.keys(event).sort();
73
+ if(keys.some(x=>!['source','timestamp','level','event','win32_error'].includes(x)))fail('unexpected event fields');
74
+ if(!/^controller-(?:start|restart)\.(?:stdout|stderr)\.log$/.test(event.source)||
75
+ !validLevels.has(event.level)||!validEvents.has(event.event))fail('non-allowlisted event value');
76
+ if(event.timestamp!==undefined&&(!/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z$/.test(event.timestamp)||Number.isNaN(Date.parse(event.timestamp))))fail('bad event time');
77
+ if(event.win32_error!==undefined&&(!Number.isInteger(event.win32_error)||event.win32_error<0||event.win32_error>65535))fail('bad Win32 code');
78
+ sources.add(event.source);
79
+ }
80
+ if(sources.size>summary.source_count)fail('event sources exceed declared sources');
81
+ return {status:'VERIFIED_LOCAL_STRUCTURE',uploaded:false,archive_sha256:sha(b),entry_count:2,summary};
82
+ }
@@ -0,0 +1,128 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {readFile,readdir} from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import {createR67ShardPlan,reconcileR67Shards,r67RegressionTreeHash,r67ShardTimeoutMs} from './r67-regression-shards.mjs';
5
+
6
+ const sha=b=>createHash('sha256').update(b).digest('hex');
7
+ const hex=x=>typeof x==='string'&&/^[a-f0-9]{64}$/.test(x);
8
+ const equal=(a,b)=>JSON.stringify(a)===JSON.stringify(b);
9
+ const idPattern=/^[a-z0-9][a-z0-9._-]{5,63}$/;
10
+ async function jsonAt(file){
11
+ try{return {value:JSON.parse(await readFile(file,'utf8'))};}
12
+ catch(e){return {error:e.code==='ENOENT'?'MISSING':'INVALID_OR_UNREADABLE'};}
13
+ }
14
+
15
+ /**
16
+ * Independent evaluator. No processes executed, no mutations. Test can inject a
17
+ * disposable root; production CLI passes the actual candidate + evidence root.
18
+ * Result hashes are integrity checks, NOT signatures.
19
+ */
20
+ export async function reconcileR67Evidence({root,evidenceRoot,operationId,sourceHashOptions}){
21
+ if(!idPattern.test(operationId??'')||typeof root!=='string'||!root||typeof evidenceRoot!=='string'||!evidenceRoot)
22
+ throw new Error('bounded root, evidence directory and operation identity required');
23
+ const testNames=(await readdir(path.join(root,'test'))).filter(n=>n.endsWith('.test.mjs')).map(n=>'test/'+n).sort();
24
+ const plan=createR67ShardPlan(testNames,32);
25
+ const hashes=[];
26
+ for(const name of testNames)hashes.push([name,sha(await readFile(path.join(root,name)))]);
27
+ const testTreeSha=sha(Buffer.from(JSON.stringify(hashes)));
28
+ const tree=await r67RegressionTreeHash(root,sourceHashOptions);
29
+ const verified=[],faults=[],stale=[],unknown=[],unclassified=[],classified=[];
30
+ for(const shard of plan.shards){
31
+ const dir=path.join(evidenceRoot,operationId+'-shard-'+String(shard.index).padStart(2,'0'));
32
+ const inFile=await jsonAt(path.join(dir,'intent.json'));
33
+ if(inFile.error==='MISSING')continue;
34
+ if(inFile.error){faults.push({index:shard.index,reason:'INTENT_'+inFile.error});continue;}
35
+ const outFile=await jsonAt(path.join(dir,'result.json'));
36
+ if(outFile.error==='MISSING'){unknown.push(shard.index);continue;}
37
+ if(outFile.error){faults.push({index:shard.index,reason:'RESULT_'+outFile.error});continue;}
38
+ const intent=inFile.value,result=outFile.value;
39
+ if(!result||typeof result!=='object'||Array.isArray(result)||!intent||typeof intent!=='object'||Array.isArray(intent)){
40
+ faults.push({index:shard.index,reason:'NOT_OBJECT'});continue;
41
+ }
42
+ const {receipt_sha256,...receiptBody}=result;
43
+ const v1=result.schema==='deadbyte.r67-shard-result.v1';
44
+ if((!v1&&result.schema!=='deadbyte.r67-shard-result.v2')||
45
+ intent.schema!=='deadbyte.r67-shard-intent.v1'||
46
+ intent.operation!==operationId||result.operation_id!==operationId||
47
+ intent.shard_index!==shard.index||result.shard_index!==shard.index||
48
+ !hex(receipt_sha256)||receipt_sha256!==sha(Buffer.from(JSON.stringify(receiptBody)))||
49
+ !hex(intent.plan_sha256)||!hex(result.plan_sha256)||
50
+ !hex(intent.files_sha256)||!hex(result.files_sha256)||
51
+ !hex(intent.test_tree_sha256)||!hex(result.test_tree_sha256)||
52
+ !Array.isArray(intent.files)||intent.files_sha256!==sha(Buffer.from(JSON.stringify(intent.files)))||
53
+ intent.plan_sha256!==result.plan_sha256||
54
+ intent.files_sha256!==result.files_sha256||
55
+ intent.test_tree_sha256!==result.test_tree_sha256||
56
+ (intent.source_tree_sha256!==undefined&&intent.source_tree_sha256!==result.source_tree_sha256)||
57
+ (intent.source_file_count!==undefined&&intent.source_file_count!==result.source_file_count)){
58
+ faults.push({index:shard.index,reason:'RESULT_DIGEST_OR_IDENTITY_INVALID'});continue;
59
+ }
60
+ if(v1){stale.push(shard.index);continue;}
61
+ if(!hex(result.source_tree_sha256)||!hex(intent.source_tree_sha256)||
62
+ !Number.isSafeInteger(result.source_file_count)||!Number.isSafeInteger(intent.source_file_count)||
63
+ !Number.isSafeInteger(result.configured_timeout_ms)||result.configured_timeout_ms<1000||
64
+ !hex(result.stdout_sha256)||!hex(result.stderr_sha256)||
65
+ typeof result.timed_out!=='boolean'||!Number.isFinite(result.elapsed_ms)||result.elapsed_ms<0||
66
+ !(result.failure_reason===null||(typeof result.failure_reason==='string'&&result.failure_reason.length>0))||
67
+ !['PASS','FAILED','OUTCOME_UNKNOWN'].includes(result.status)||
68
+ (result.status==='PASS'&&(result.timed_out||result.failure_reason!==null||result.exit_code!==0))){
69
+ faults.push({index:shard.index,reason:'V2_CONTRACT_INVALID'});continue;
70
+ }
71
+ if(result.nonpass_cases!==undefined){
72
+ const cases=result.nonpass_cases;
73
+ const valid=Array.isArray(cases)&&cases.length<=10000&&
74
+ cases.every(c=>c&&typeof c==='object'&&!Array.isArray(c)&&
75
+ ['SKIP','TODO'].includes(c.kind)&&typeof c.name==='string'&&
76
+ c.name.length>=1&&c.name.length<=256&&!/[\x00-\x1f\x7f-\x9f]/u.test(c.name)&&
77
+ (c.reason===null||(typeof c.reason==='string'&&c.reason.length>=1&&c.reason.length<=256&&!/[\x00-\x1f\x7f-\x9f]/u.test(c.reason))))&&
78
+ cases.filter(c=>c.kind==='SKIP').length===result.skipped&&
79
+ cases.filter(c=>c.kind==='TODO').length===result.todo&&
80
+ result.nonpass_fully_classified===cases.every(c=>c.reason!==null);
81
+ if(!valid){faults.push({index:shard.index,reason:'NONPASS_LEDGER_INVALID'});continue;}
82
+ }
83
+ if(intent.test_tree_sha256!==testTreeSha||result.source_tree_sha256!==tree.sha256||
84
+ result.source_file_count!==tree.file_count||
85
+ result.configured_timeout_ms!==r67ShardTimeoutMs(shard)||
86
+ intent.plan_sha256!==plan.plan_sha256||intent.files_sha256!==shard.files_sha256){
87
+ stale.push(shard.index);continue;
88
+ }
89
+ // New failure identity extension applies only to current-source receipts; pre-extension
90
+ // historical v2 receipts stay STALE_SOURCE rather than a fabricated tampering charge.
91
+ if(result.failure_cases!==undefined||result.failure_cases_complete!==undefined||result.failed>0){
92
+ const cases=result.failure_cases;
93
+ const valid=Array.isArray(cases)&&cases.length<=128&&
94
+ typeof result.failure_cases_complete==='boolean'&&
95
+ cases.every(c=>c&&typeof c==='object'&&!Array.isArray(c)&&
96
+ Object.keys(c).sort().join('|')==='name|name_sha256'&&
97
+ typeof c.name==='string'&&c.name.length>0&&c.name.length<=256&&
98
+ !/[\x00-\x1f\x7f-\x9f]/u.test(c.name)&&hex(c.name_sha256)&&
99
+ (c.name==='[redacted]'||sha(Buffer.from(c.name,'utf8'))===c.name_sha256))&&
100
+ (result.failure_cases_complete?cases.length===result.failed:cases.length<=result.failed);
101
+ if(!valid){faults.push({index:shard.index,reason:'FAILED_CASE_LEDGER_INVALID'});continue;}
102
+ }
103
+ verified.push(result);
104
+ if(result.status==='OUTCOME_UNKNOWN')unknown.push(shard.index);
105
+ if(result.skipped>0||result.todo>0||result.cancelled>0){
106
+ const caseEvidence={index:shard.index,skipped:result.skipped,todo:result.todo,cancelled:result.cancelled,...(Array.isArray(result.nonpass_cases)?{cases:result.nonpass_cases}:{}),...(typeof result.nonpass_fully_classified==='boolean'?{fully_classified:result.nonpass_fully_classified}:{})};
107
+ if(result.cancelled===0&&result.todo===0&&result.nonpass_fully_classified===true&&
108
+ Array.isArray(result.nonpass_cases)&&result.nonpass_cases.length===result.skipped&&
109
+ result.nonpass_cases.every(c=>c.kind==='SKIP'&&typeof c.reason==='string'&&c.reason.trim().length>0))classified.push(caseEvidence);
110
+ else unclassified.push(caseEvidence);
111
+ }
112
+ }
113
+ const verdict=reconcileR67Shards(plan,verified);
114
+ const status=faults.length?'FAILED_INTEGRITY':
115
+ stale.length?'STALE_SOURCE':
116
+ unknown.length?'OUTCOME_UNKNOWN':
117
+ verdict.status!=='PASS'?verdict.status:
118
+ unclassified.length?'BLOCKED_NONPASS_CLASSIFICATION':'PASS';
119
+ return {
120
+ schema:'deadbyte.r67-persistent-regression-reconciliation.v2',
121
+ operation_id:operationId,status,plan_sha256:plan.plan_sha256,
122
+ test_tree_sha256:testTreeSha,source_tree_sha256:tree.sha256,
123
+ source_file_count:tree.file_count,test_file_count:plan.file_count,
124
+ verified_receipts:verified.length,integrity_faults:faults,
125
+ stale_indices:stale,unknown_indices:unknown,unclassified_nonpass:unclassified,classified_nonpass:classified,
126
+ verdict,production_mutation_performed:false
127
+ };
128
+ }
@@ -0,0 +1,45 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {codingSessionStatus} from './coding-plane.mjs';
3
+
4
+ const HEX64=/^[0-9a-f]{64}$/;
5
+ const hash=s=>createHash('sha256').update(s,'utf8').digest('hex');
6
+
7
+ /**
8
+ * A server-owned callback, never a model-supplied permission.
9
+ * Opt-in is separate from the coding standing grant; every request and its
10
+ * completion re-reads the live epoch and checks revocation.
11
+ */
12
+ export function createR67NativeObservationAuthority({
13
+ getCodingPolicy,
14
+ enabled=false,
15
+ sessionStatus=codingSessionStatus,
16
+ rootId='projects'
17
+ }={}){
18
+ if(typeof getCodingPolicy!=='function'||typeof sessionStatus!=='function')throw new TypeError('trusted runtime authority providers required');
19
+ if(typeof enabled!=='boolean')throw new TypeError('native observer opt-in must be boolean');
20
+ return async ({operation,args}={})=>{
21
+ if(!enabled)throw new Error('R67_NATIVE_OBSERVATION_DISABLED');
22
+ if(!['process','identity','map'].includes(operation)||!Array.isArray(args)||args[0]!==operation)
23
+ throw new Error('R67_NATIVE_OBSERVATION_SCOPE_DENIED');
24
+ if(operation==='map'&&args[1]!=='self')throw new Error('R67_NATIVE_OBSERVATION_OTHER_PID_DENIED');
25
+ if(operation==='identity'&&args[1]!=='self')throw new Error('R67_NATIVE_OBSERVATION_OTHER_PID_DENIED');
26
+ const policy=getCodingPolicy();
27
+ if(!policy||!HEX64.test(policy.policy_sha256??'')||!policy.roots?.[rootId]?.read)
28
+ throw new Error('R67_NATIVE_OBSERVATION_POLICY_MISSING');
29
+ const lease=await sessionStatus(policy);
30
+ const epoch=lease?.authority_epoch;
31
+ if(!lease?.armed||lease.standing!==true||lease.reason!=='standing-grant'||
32
+ !Array.isArray(lease.root_ids)||!lease.root_ids.includes(rootId)||
33
+ !HEX64.test(lease.instance_nonce??'')||
34
+ epoch?.trusted!==true||!Number.isSafeInteger(epoch.seq)||epoch.seq<1||
35
+ !HEX64.test(epoch.event_sha256??''))
36
+ throw new Error('R67_NATIVE_OBSERVATION_AUTHORITY_REVOKED');
37
+ const grantId='coding.r67.'+hash(lease.instance_nonce+':'+epoch.event_sha256).slice(0,32);
38
+ return Object.freeze({
39
+ grant_id:grantId,
40
+ policy_sha256:policy.policy_sha256,
41
+ scope:'native-observe-readonly',
42
+ authority_generation:epoch.seq
43
+ });
44
+ };
45
+ }
@@ -0,0 +1,43 @@
1
+ import {createHash,createPublicKey,sign as edSign} from 'node:crypto';
2
+
3
+ export const R67_OBSERVATION_DOMAIN=Buffer.from('DEADBYTE-R67-OBSERVATION-V1\0','utf8');
4
+ const isHex64=s=>typeof s==='string'&&/^[a-f0-9]{64}$/.test(s);
5
+ const sha=b=>createHash('sha256').update(b).digest('hex');
6
+ const canonical=value=>JSON.stringify(
7
+ Array.isArray(value)?value.map(v=>JSON.parse(canonical(v))):
8
+ value!==null&&typeof value==='object'?
9
+ Object.fromEntries(Object.keys(value).sort().map(k=>[k,JSON.parse(canonical(value[k]))])):
10
+ value
11
+ );
12
+ export const hashR67Result=result=>sha(Buffer.from(canonical(result),'utf8'));
13
+
14
+ export function signR67Observation({privateKey,publicKey,operation,requestSha256,executableSha256,result,observedAtUtc=new Date().toISOString()}){
15
+ if(!privateKey||!publicKey)throw new Error('R67 receipt signer must be supplied by trusted runtime; no implicit key generation');
16
+ if(!['process','identity','map','pe'].includes(operation)||!isHex64(requestSha256)||!isHex64(executableSha256))
17
+ throw new Error('R67 observation operation and 256-bit bindings required');
18
+ if(!result||result.schema!=='deadbyte.native-inspect.r67.v1'||!['ok','failed'].includes(result.status))
19
+ throw new Error('R67 result contract invalid');
20
+ if(result.status==='ok'&&(result.operation!==operation||!isHex64(result.data_sha256)||!result.data||
21
+ result.data_sha256!==sha(Buffer.from(JSON.stringify(result.data),'utf8'))))throw new Error('R67 result data digest invalid');
22
+ const timestamp=new Date(observedAtUtc);
23
+ if(!Number.isFinite(timestamp.getTime())||timestamp.toISOString()!==observedAtUtc)throw new Error('R67 observation timestamp invalid');
24
+ const key=publicKey?.type==='public'?publicKey:createPublicKey(publicKey);
25
+ const derived=createPublicKey(privateKey);
26
+ const spki=Buffer.from(key.export({type:'spki',format:'der'}));
27
+ const derivedSpki=Buffer.from(derived.export({type:'spki',format:'der'}));
28
+ if(key.asymmetricKeyType!=='ed25519'||!spki.equals(derivedSpki))throw new Error('R67 signer public/private identity mismatch');
29
+ const body={
30
+ schema:'deadbyte.native-observation-receipt.r67.v1',
31
+ observed_at_utc:observedAtUtc,
32
+ operation,
33
+ request_sha256:requestSha256,
34
+ executable_sha256:executableSha256,
35
+ result_status:result.status,
36
+ result_sha256:hashR67Result(result),
37
+ signer_key_id:sha(spki)
38
+ };
39
+ const receipt_sha256=sha(Buffer.from(canonical(body),'utf8'));
40
+ const signed={...body,receipt_sha256};
41
+ const signature=edSign(null,Buffer.concat([R67_OBSERVATION_DOMAIN,Buffer.from(canonical(signed),'utf8')]),privateKey);
42
+ return {...signed,attestation:{algorithm:'ed25519',key_id:body.signer_key_id,signature_base64:signature.toString('base64')}};
43
+ }