deadbyte-mcp 0.15.38 → 0.15.41

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 (42) hide show
  1. package/MANIFEST.SHA256 +41 -21
  2. package/PROVENANCE.json +75 -21
  3. package/README.txt +30 -18
  4. package/RELEASE.json +76 -22
  5. package/SBOM.cdx.json +2 -2
  6. package/TEST-MATRIX.json +78 -26
  7. package/bridge/package.json +1 -1
  8. package/controller/deadbyte-process-policy.json +4 -4
  9. package/docs/R64-EVIDENCE.json +95 -0
  10. package/docs/R64-REFERENCE-GAP-MATRIX.json +98 -0
  11. package/docs/R64-SCOPE.json +41 -0
  12. package/package.json +6 -3
  13. package/scripts/gate-windows-r62-prepublish.ps1 +45 -0
  14. package/scripts/gate-windows-r63-prepublish.ps1 +45 -0
  15. package/scripts/gate-windows-r64-prepublish.ps1 +68 -0
  16. package/scripts/npm-release-r48.mjs +6 -0
  17. package/scripts/r62-focused.ps1 +9 -0
  18. package/scripts/r62-full.ps1 +9 -0
  19. package/scripts/r62-live-transaction-audit.mjs +17 -0
  20. package/scripts/r62-unresolved-transaction-inspect.mjs +54 -0
  21. package/scripts/r64-predecessor-reproducer.mjs +32 -0
  22. package/scripts/r64-read-benchmark.mjs +84 -0
  23. package/src/compact-gateway-mcp-tools.mjs +1 -1
  24. package/src/deadbyte-cli.mjs +16 -2
  25. package/src/doctor-transactions-r58.mjs +79 -8
  26. package/src/machine-fs-mcp-tools.mjs +1 -1
  27. package/src/machine-fs.mjs +7 -4
  28. package/src/remote-authority.mjs +10 -0
  29. package/src/runtime-update.mjs +15 -3
  30. package/src/version.mjs +1 -1
  31. package/test/r58-doctor-transactions.test.mjs +2 -2
  32. package/test/r59-tool-surface-compat.test.mjs +14 -4
  33. package/test/r61-release-contract.test.mjs +2 -1
  34. package/test/r62-doctor-receipt-semantics.test.mjs +50 -0
  35. package/test/r62-doctor-transactions-reconcile.test.mjs +208 -0
  36. package/test/r62-release-contract.test.mjs +60 -0
  37. package/test/r62-rollback-failure-receipt.test.mjs +19 -0
  38. package/test/r63-one-shot-coherence.test.mjs +38 -0
  39. package/test/r63-release-contract.test.mjs +59 -0
  40. package/test/r64-machine-fs-large-read.test.mjs +136 -0
  41. package/test/r64-release-contract.test.mjs +51 -0
  42. package/test/remote-session-cli.test.mjs +7 -5
@@ -0,0 +1,208 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {mkdir,mkdtemp,writeFile,readFile} from 'node:fs/promises';
4
+ import {generateKeyPairSync,createHash,sign} from 'node:crypto';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import {inspectDoctorTransactions} from '../src/doctor-transactions-r58.mjs';
8
+
9
+ const sha=b=>createHash('sha256').update(b).digest('hex');
10
+ const canonical=value=>Array.isArray(value)?value.map(canonical):value&&typeof value==='object'
11
+ ?Object.fromEntries(Object.keys(value).sort().map(key=>[key,canonical(value[key])])):value;
12
+ const canonicalJson=value=>JSON.stringify(canonical(value));
13
+ const domain=Buffer.from('DEADBYTE-R27-SLOT-UPDATE-V1\0');
14
+
15
+ function envelope(body,keys){
16
+ const bodyBytes=Buffer.from(canonicalJson(body),'utf8');
17
+ const unsigned={
18
+ body,
19
+ body_sha256:sha(bodyBytes),
20
+ attestation:{
21
+ algorithm:'ed25519',
22
+ domain:'DEADBYTE-R27-SLOT-UPDATE-V1',
23
+ key_id:sha(keys.publicKey.export({type:'spki',format:'der'})),
24
+ signature_base64:sign(null,Buffer.concat([domain,bodyBytes]),keys.privateKey).toString('base64')
25
+ }
26
+ };
27
+ return {...unsigned,receipt_sha256:sha(Buffer.from(canonicalJson(unsigned),'utf8'))};
28
+ }
29
+
30
+ test('R62 doctor reconciles signed terminal receipts instead of warning on stale nonterminal journal phases',async()=>{
31
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r62-doctor-reconcile-'));
32
+ const trust=path.join(root,'trust');
33
+ const updates=path.join(root,'evidence','updates');
34
+ await mkdir(trust,{recursive:true});
35
+ await mkdir(updates,{recursive:true});
36
+ const keys=generateKeyPairSync('ed25519');
37
+ await writeFile(path.join(trust,'ed25519-public.pem'),keys.publicKey.export({type:'spki',format:'pem'}));
38
+
39
+ const writeTransaction=async(name,state,receiptName,receiptBody)=>{
40
+ const dir=path.join(updates,name);
41
+ await mkdir(dir);
42
+ const statePath=path.join(dir,'state.json');
43
+ const stateBytes=JSON.stringify(state);
44
+ await writeFile(statePath,stateBytes);
45
+ await writeFile(path.join(dir,receiptName),JSON.stringify(envelope(receiptBody,keys)));
46
+ return {statePath,stateBytes};
47
+ };
48
+
49
+ const success=await writeTransaction(
50
+ 'success',
51
+ {schema:'deadbyte.r27-slot-update-state.v1',update_id:'success',phase:'pointer_committed'},
52
+ 'receipt.json',
53
+ {schema:'deadbyte.r27-slot-update-receipt.v1',update_id:'success',rollback_performed:false}
54
+ );
55
+ const failure=await writeTransaction(
56
+ 'failure',
57
+ {schema:'deadbyte.r27-slot-update-state.v1',update_id:'failure',phase:'candidate_prepared'},
58
+ 'failure-receipt.json',
59
+ {schema:'deadbyte.r27-slot-update-failure.v1',update_id:'failure',failed_at_utc:'2026-10-04T00:00:00.000Z'}
60
+ );
61
+
62
+ const result=await inspectDoctorTransactions(root);
63
+ assert.equal(result.status,'PASS');
64
+ assert.equal(result.findings.some(f=>f.level==='WARN'),false);
65
+ const summary=result.findings.find(f=>f.evidence?.receipt_verification_performed===true);
66
+ assert.ok(summary,'doctor must report signed receipt verification');
67
+ assert.equal(summary.evidence.verified_terminal_receipts,2);
68
+ assert.equal(summary.evidence.unresolved_transactions,0);
69
+ assert.equal(await readFile(success.statePath,'utf8'),success.stateBytes);
70
+ assert.equal(await readFile(failure.statePath,'utf8'),failure.stateBytes);
71
+ });
72
+
73
+
74
+ test('R62 doctor default transaction budget covers more than the legacy 256-entry ceiling while remaining bounded',async()=>{
75
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r62-doctor-budget-'));
76
+ const updates=path.join(root,'evidence','updates');
77
+ await mkdir(updates,{recursive:true});
78
+ for(let index=0;index<300;index++){
79
+ const dir=path.join(updates,`tx-${String(index).padStart(3,'0')}`);
80
+ await mkdir(dir);
81
+ await writeFile(path.join(dir,'state.json'),JSON.stringify({
82
+ schema:'deadbyte.r27-slot-update-state.v1',
83
+ update_id:`tx-${index}`,
84
+ phase:'superseded'
85
+ }));
86
+ }
87
+ const result=await inspectDoctorTransactions(root);
88
+ assert.equal(result.status,'PASS');
89
+ assert.equal(result.findings.some(f=>f.evidence?.inventory_complete===false),false);
90
+ const summary=result.findings.find(f=>f.evidence?.receipt_verification_performed===true);
91
+ assert.ok(summary);
92
+ assert.equal(summary.evidence.states_checked,300);
93
+ await assert.rejects(inspectDoctorTransactions(root,{maxEntries:1025}),/budget invalid/);
94
+ });
95
+
96
+
97
+ test('R62 doctor verifies signed receipts even when the journal already claims a terminal phase',async()=>{
98
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r62-doctor-terminal-proof-'));
99
+ const trust=path.join(root,'trust');
100
+ const updates=path.join(root,'evidence','updates');
101
+ await mkdir(trust,{recursive:true});
102
+ await mkdir(updates,{recursive:true});
103
+ const keys=generateKeyPairSync('ed25519');
104
+ await writeFile(path.join(trust,'ed25519-public.pem'),keys.publicKey.export({type:'spki',format:'pem'}));
105
+
106
+ const provenDir=path.join(updates,'proven');
107
+ await mkdir(provenDir);
108
+ await writeFile(path.join(provenDir,'state.json'),JSON.stringify({
109
+ schema:'deadbyte.r27-slot-update-state.v1',
110
+ update_id:'proven',
111
+ phase:'completed'
112
+ }));
113
+ await writeFile(path.join(provenDir,'receipt.json'),JSON.stringify(envelope({
114
+ schema:'deadbyte.r27-slot-update-receipt.v1',
115
+ update_id:'proven',
116
+ rollback_performed:false
117
+ },keys)));
118
+
119
+ const proven=await inspectDoctorTransactions(root);
120
+ assert.equal(proven.status,'PASS');
121
+ const provenSummary=proven.findings.find(f=>f.evidence?.receipt_verification_performed===true);
122
+ assert.equal(provenSummary.evidence.verified_terminal_receipts,1);
123
+
124
+ const unprovenDir=path.join(updates,'unproven');
125
+ await mkdir(unprovenDir);
126
+ await writeFile(path.join(unprovenDir,'state.json'),JSON.stringify({
127
+ schema:'deadbyte.r27-slot-update-state.v1',
128
+ update_id:'unproven',
129
+ phase:'completed'
130
+ }));
131
+ const unproven=await inspectDoctorTransactions(root);
132
+ assert.equal(unproven.status,'WARN');
133
+ assert.ok(unproven.findings.some(f=>f.evidence?.recorded_phase==='completed'));
134
+ });
135
+
136
+
137
+ test('R62 doctor fails closed on tampered or missing claimed terminal receipts without mutating journals',async()=>{
138
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r62-doctor-adversarial-'));
139
+ const trust=path.join(root,'trust');
140
+ const updates=path.join(root,'evidence','updates');
141
+ await mkdir(trust,{recursive:true});
142
+ await mkdir(updates,{recursive:true});
143
+ const keys=generateKeyPairSync('ed25519');
144
+ await writeFile(path.join(trust,'ed25519-public.pem'),keys.publicKey.export({type:'spki',format:'pem'}));
145
+
146
+ const tamperedDir=path.join(updates,'tampered');
147
+ await mkdir(tamperedDir);
148
+ const tamperedStatePath=path.join(tamperedDir,'state.json');
149
+ const tamperedState=JSON.stringify({
150
+ schema:'deadbyte.r27-slot-update-state.v1',
151
+ update_id:'tampered',
152
+ phase:'completed'
153
+ });
154
+ await writeFile(tamperedStatePath,tamperedState);
155
+ const good=envelope({
156
+ schema:'deadbyte.r27-slot-update-receipt.v1',
157
+ update_id:'tampered',
158
+ rollback_performed:false
159
+ },keys);
160
+ const bad={...good,attestation:{...good.attestation,signature_base64:Buffer.alloc(64).toString('base64')}};
161
+ await writeFile(path.join(tamperedDir,'receipt.json'),JSON.stringify(bad));
162
+
163
+ const missingDir=path.join(updates,'missing');
164
+ await mkdir(missingDir);
165
+ const missingStatePath=path.join(missingDir,'state.json');
166
+ const missingState=JSON.stringify({
167
+ schema:'deadbyte.r27-slot-update-state.v1',
168
+ update_id:'missing',
169
+ phase:'failed_receipted'
170
+ });
171
+ await writeFile(missingStatePath,missingState);
172
+
173
+ const result=await inspectDoctorTransactions(root);
174
+ assert.equal(result.status,'FAIL');
175
+ assert.ok(result.findings.some(f=>f.evidence?.check==='terminal_receipt_verification'));
176
+ assert.ok(result.findings.some(f=>f.evidence?.check==='missing_failure_receipt'));
177
+ assert.equal(await readFile(tamperedStatePath,'utf8'),tamperedState);
178
+ assert.equal(await readFile(missingStatePath,'utf8'),missingState);
179
+ });
180
+
181
+
182
+ test('R62 doctor reconciles a signed R31 rollback failure receipt by rollback_id',async()=>{
183
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r62-r31-failure-proof-'));
184
+ const trust=path.join(root,'trust');
185
+ const dir=path.join(root,'evidence','updates','rollback-failure');
186
+ await mkdir(trust,{recursive:true});
187
+ await mkdir(dir,{recursive:true});
188
+ const keys=generateKeyPairSync('ed25519');
189
+ await writeFile(path.join(trust,'ed25519-public.pem'),keys.publicKey.export({type:'spki',format:'pem'}));
190
+ const rollbackId='r31-rollback-r62-fixture';
191
+ await writeFile(path.join(dir,'state.json'),JSON.stringify({
192
+ schema:'deadbyte.r31-slot-rollback-state.v1',
193
+ rollback_id:rollbackId,
194
+ phase:'failed'
195
+ }));
196
+ await writeFile(path.join(dir,'failure-receipt.json'),JSON.stringify(envelope({
197
+ schema:'deadbyte.r31-slot-rollback-failure.v1',
198
+ rollback_id:rollbackId,
199
+ failed_at_utc:'2026-10-04T00:00:00.000Z',
200
+ error:{name:'Error',message:'fixture'}
201
+ },keys)));
202
+ const result=await inspectDoctorTransactions(root);
203
+ assert.equal(result.status,'PASS');
204
+ const summary=result.findings.find(f=>f.evidence?.receipt_verification_performed===true);
205
+ assert.equal(summary.evidence.verified_terminal_receipts,1);
206
+ assert.equal(summary.evidence.verified_failure_receipts,1);
207
+ assert.equal(summary.evidence.unresolved_transactions,0);
208
+ });
@@ -0,0 +1,60 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {readFile} from 'node:fs/promises';
4
+
5
+ const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
6
+ const json=rel=>read(rel).then(raw=>JSON.parse(raw.replace(/^\uFEFF/,'')));
7
+ const currentPackage=await json('package.json');
8
+ const PARENT={
9
+ version:'0.15.38',
10
+ release_id:'v0.15.38-917901b3fcb2a77f',
11
+ manifest_sha256:'917901b3fcb2a77f696fedc539bd97c567d9dc59345779906fc633d11ea4bcfb',
12
+ generation_manifest_sha256:'9d320a8af1ba8e9e6a23552f35263da2670c00af1355464820552d849d9033c6'
13
+ };
14
+
15
+ test('R62 identity binds exact sealed 0.15.38 parent and transaction reconciliation scope',{skip:currentPackage.version!=='0.15.39'},async()=>{
16
+ const [pkg,lock,bridge,release,provenance,matrix,sbom,version,gate]=await Promise.all([
17
+ json('package.json'),json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
18
+ json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),
19
+ read('scripts/gate-windows-r62-prepublish.ps1')
20
+ ]);
21
+ assert.equal(pkg.version,'0.15.39');
22
+ assert.equal(lock.version,pkg.version);
23
+ assert.equal(lock.packages[''].version,pkg.version);
24
+ assert.equal(bridge.version,pkg.version);
25
+ assert.match(version,/DEADBYTE_VERSION = '0\.15\.39'/);
26
+ assert.equal(release.version,pkg.version);
27
+ assert.equal(release.train,'R62');
28
+ assert.equal(release.parent.version,PARENT.version);
29
+ assert.equal(release.parent.release_id,PARENT.release_id);
30
+ assert.equal(release.parent.manifest_sha256,PARENT.manifest_sha256);
31
+ assert.equal(release.parent.generation_manifest_sha256,PARENT.generation_manifest_sha256);
32
+ assert.deepEqual(release.runtime_predecessor,{
33
+ release_id:PARENT.release_id,
34
+ manifest_sha256:PARENT.manifest_sha256,
35
+ generation_manifest_sha256:PARENT.generation_manifest_sha256
36
+ });
37
+ assert.equal(provenance.version,pkg.version);
38
+ assert.equal(provenance.parent_release_id,PARENT.release_id);
39
+ assert.equal(provenance.parent_manifest_sha256,PARENT.manifest_sha256);
40
+ assert.equal(provenance.parent_generation_manifest_sha256,PARENT.generation_manifest_sha256);
41
+ assert.equal(matrix.version,pkg.version);
42
+ assert.equal(matrix.train,'R62');
43
+ assert.equal(sbom.metadata.component.version,pkg.version);
44
+ assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r62:0.15.39');
45
+ assert.equal(release.r62_transaction_reconciliation.public_surface_tool_count,43);
46
+ assert.equal(release.r62_transaction_reconciliation.new_authority_scopes,0);
47
+ assert.equal(release.r62_transaction_reconciliation.signed_terminal_receipt_reconciliation,true);
48
+ assert.equal(release.r62_transaction_reconciliation.r31_signed_failure_receipts,true);
49
+ assert.equal(release.r62_transaction_reconciliation.transaction_inventory_default_max_entries,1024);
50
+ assert.equal(release.r62_transaction_reconciliation.historical_unsigned_residue_preserved,true);
51
+ assert.equal(release.r62_transaction_reconciliation.stable_final_claim,false);
52
+ assert.match(pkg.scripts['r62:focused:test'],/r62-doctor-transactions-reconcile\.test\.mjs/);
53
+ assert.match(pkg.scripts['r62:focused:test'],/r62-rollback-failure-receipt\.test\.mjs/);
54
+ assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r62-prepublish.ps1');
55
+ assert.match(gate,/v0\.15\.38-917901b3fcb2a77f/);
56
+ assert.match(gate,/917901b3fcb2a77f696fedc539bd97c567d9dc59345779906fc633d11ea4bcfb/);
57
+ assert.match(gate,/9d320a8af1ba8e9e6a23552f35263da2670c00af1355464820552d849d9033c6/);
58
+ assert.match(gate,/r62:focused:test/);
59
+ assert.doesNotMatch(gate,/v0\.15\.37-1cfecd7889419da7/);
60
+ });
@@ -0,0 +1,19 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {readFile} from 'node:fs/promises';
4
+
5
+ test('R62 R31 rollback failures emit a signed subject-bound failure receipt before returning failure',async()=>{
6
+ const source=await readFile(new URL('../src/runtime-update.mjs',import.meta.url),'utf8');
7
+ assert.match(source,/const ROLLBACK_FAILURE_SCHEMA='deadbyte\.r31-slot-rollback-failure\.v1'/);
8
+ const start=source.indexOf('export async function performSlotRollback');
9
+ const end=source.indexOf('export async function runSlotUpdateCli',start);
10
+ assert.ok(start>=0&&end>start);
11
+ const perform=source.slice(start,end);
12
+ assert.match(perform,/failurePath=path\.join\(evidenceDir,'failure-receipt\.json'\)/);
13
+ assert.match(perform,/schema:ROLLBACK_FAILURE_SCHEMA/);
14
+ assert.match(perform,/rollback_id:rollbackId/);
15
+ assert.match(perform,/activation_receipt_sha256:activationEnvelope\.receipt_sha256/);
16
+ assert.match(perform,/await writeEnvelope\(failurePath,failure,key\)/);
17
+ assert.match(perform,/writeState\(statePath,journal,'failed_receipted'/);
18
+ assert.match(perform,/wrapped\.failureReceiptPath=failureReceipt\?failurePath:null/);
19
+ });
@@ -0,0 +1,38 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { readFile } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const root=path.resolve(fileURLToPath(new URL('..',import.meta.url)));
8
+ const authority=await import('../src/remote-authority.mjs');
9
+
10
+ test('R63 one-shot upgrade restore plan reproduces the exact pre-upgrade authority vector',()=>{
11
+ assert.equal(typeof authority.authorityRestorePlan,'function','authorityRestorePlan must exist');
12
+ const snapshot={
13
+ authority:{
14
+ process:{configured:true,armed:true,reason:'standing-grant'},
15
+ coding:{configured:true,armed:true,reason:'standing-grant'},
16
+ autonomous:{configured:true,armed:true,reason:'standing-grant'},
17
+ desktop:{configured:true,armed:false,reason:'disarmed'},
18
+ host:{configured:true,armed:true,reason:'standing-grant'}
19
+ }
20
+ };
21
+ assert.deepEqual(authority.authorityRestorePlan(snapshot),[
22
+ 'disarmdesktop',
23
+ 'armprocess','armcoding','armautonomous','armhost'
24
+ ]);
25
+ });
26
+
27
+ test('R63 explicit remote command synchronizes runtime before dispatch instead of warn-only skew reporting',async()=>{
28
+ const source=await readFile(path.join(root,'src','deadbyte-cli.mjs'),'utf8');
29
+ const start=source.indexOf('async function runRemote(args){');
30
+ const end=source.indexOf('\nasync function runSupervisor(',start);
31
+ assert.ok(start>=0&&end>start,'runRemote source boundary missing');
32
+ const body=source.slice(start,end);
33
+ const sync=body.indexOf("await synchronizeOneShotRuntime(ctx,{displayMode:'ascii'});");
34
+ const dispatch=body.indexOf('invokeController(ctx,command,{allowFailure:true})');
35
+ assert.ok(sync>=0,'one-shot remote command must synchronize the active runtime');
36
+ assert.ok(dispatch>sync,'runtime synchronization must complete before controller dispatch');
37
+ assert.doesNotMatch(body,/reportVersionCoherence/,'warn-only skew path must not remain in one-shot dispatch');
38
+ });
@@ -0,0 +1,59 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {readFile} from 'node:fs/promises';
4
+
5
+ const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
6
+ const json=rel=>read(rel).then(raw=>JSON.parse(raw.replace(/^\uFEFF/,'')));
7
+ const currentPackage=await json('package.json');
8
+ const PARENT={
9
+ version:'0.15.39',
10
+ release_id:'v0.15.39-3cda3b1c65b7b7c5',
11
+ manifest_sha256:'3cda3b1c65b7b7c561c5a8617156ab87d69cf162f447f3e99a4cb4a76471b3de',
12
+ generation_manifest_sha256:'f47cb96083679e764725df1bde6eda53169a39f55772c173ab22f89a1dfaa7ab'
13
+ };
14
+
15
+ test('R63 identity binds exact active 0.15.39 parent and one-shot runtime coherence repair',{skip:currentPackage.version!=='0.15.40'},async()=>{
16
+ const pkg=await json('package.json');
17
+ assert.equal(pkg.version,'0.15.40');
18
+ assert.match(pkg.scripts['r63:focused:test'],/r63-one-shot-coherence\.test\.mjs/);
19
+ assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r63-prepublish.ps1');
20
+
21
+ const [lock,bridge,release,provenance,matrix,sbom,version,gate]=await Promise.all([
22
+ json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),json('PROVENANCE.json'),
23
+ json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),read('scripts/gate-windows-r63-prepublish.ps1')
24
+ ]);
25
+ assert.equal(lock.version,pkg.version);
26
+ assert.equal(lock.packages[''].version,pkg.version);
27
+ assert.equal(bridge.version,pkg.version);
28
+ assert.match(version,/DEADBYTE_VERSION = '0\.15\.40'/);
29
+ assert.equal(release.version,pkg.version);
30
+ assert.equal(release.train,'R63');
31
+ assert.equal(release.parent.version,PARENT.version);
32
+ assert.equal(release.parent.release_id,PARENT.release_id);
33
+ assert.equal(release.parent.manifest_sha256,PARENT.manifest_sha256);
34
+ assert.equal(release.parent.generation_manifest_sha256,PARENT.generation_manifest_sha256);
35
+ assert.deepEqual(release.runtime_predecessor,{
36
+ release_id:PARENT.release_id,
37
+ manifest_sha256:PARENT.manifest_sha256,
38
+ generation_manifest_sha256:PARENT.generation_manifest_sha256
39
+ });
40
+ assert.equal(provenance.version,pkg.version);
41
+ assert.equal(provenance.parent_release_id,PARENT.release_id);
42
+ assert.equal(provenance.parent_manifest_sha256,PARENT.manifest_sha256);
43
+ assert.equal(provenance.parent_generation_manifest_sha256,PARENT.generation_manifest_sha256);
44
+ assert.equal(matrix.version,pkg.version);
45
+ assert.equal(matrix.train,'R63');
46
+ assert.equal(sbom.metadata.component.version,pkg.version);
47
+ assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r63:0.15.40');
48
+ assert.equal(release.r63_one_shot_runtime_coherence.public_surface_tool_count,43);
49
+ assert.equal(release.r63_one_shot_runtime_coherence.new_authority_scopes,0);
50
+ assert.equal(release.r63_one_shot_runtime_coherence.one_shot_auto_coherence,true);
51
+ assert.equal(release.r63_one_shot_runtime_coherence.pre_upgrade_authority_snapshot,true);
52
+ assert.equal(release.r63_one_shot_runtime_coherence.exact_authority_restore_verified,true);
53
+ assert.equal(release.r63_one_shot_runtime_coherence.warn_only_skew_path_removed,true);
54
+ assert.equal(release.r63_one_shot_runtime_coherence.stable_final_claim,false);
55
+ assert.match(gate,/v0\.15\.39-3cda3b1c65b7b7c5/);
56
+ assert.match(gate,/3cda3b1c65b7b7c561c5a8617156ab87d69cf162f447f3e99a4cb4a76471b3de/);
57
+ assert.match(gate,/f47cb96083679e764725df1bde6eda53169a39f55772c173ab22f89a1dfaa7ab/);
58
+ assert.match(gate,/r63:focused:test/);
59
+ });
@@ -0,0 +1,136 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {createHash} from 'node:crypto';
4
+ import fs from 'node:fs';
5
+ import {EventEmitter} from 'node:events';
6
+ import {mkdtemp, mkdir, readFile, writeFile, rm} from 'node:fs/promises';
7
+ import {syncBuiltinESMExports} from 'node:module';
8
+ import {tmpdir} from 'node:os';
9
+ import path from 'node:path';
10
+ import {loadCodingPolicy} from '../src/coding-plane.mjs';
11
+ import {createMachineFsRuntime} from '../src/machine-fs.mjs';
12
+ import {generateTrustKeypair} from '../src/trust.mjs';
13
+ import {machineFsGatewayInputSchema} from '../src/compact-gateway-mcp-tools.mjs';
14
+ import {registerMachineFsTools} from '../src/machine-fs-mcp-tools.mjs';
15
+
16
+ const PAGE=4*1024*1024;
17
+
18
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
19
+
20
+ async function fixture(t,{read=true}={}){
21
+ const root=await mkdtemp(path.join(tmpdir(),'deadbyte-r64-read-'));
22
+ t.after(()=>rm(root,{recursive:true,force:true}));
23
+ const project=path.join(root,'project');
24
+ await mkdir(project);
25
+ const policyPath=path.join(root,'policy.json');
26
+ await writeFile(policyPath,JSON.stringify({
27
+ schema:'deadbyte.coding-policy.v1',enabled:true,
28
+ lease_file:path.join(root,'coding-grant.json'),evidence_dir:path.join(root,'evidence'),
29
+ roots:{project:{path:project,read,write:false,exec:false,deny_paths:[]}},
30
+ commands:{},max_read_bytes:PAGE,max_write_bytes:65536
31
+ }));
32
+ const policy=await loadCodingPolicy(policyPath);
33
+ const keys=await generateTrustKeypair({privateKeyPath:path.join(root,'private.pem'),publicKeyPath:path.join(root,'public.pem')});
34
+ return {root,project,policy,keys,runtime:createMachineFsRuntime({policy,signingKeyPath:keys.privateKeyPath,verifyKeyPath:keys.publicKeyPath})};
35
+ }
36
+
37
+ test('R64 full and compact read schemas accept next_offset beyond one-page bound',()=>{
38
+ const server={registerTool(name,definition){if(name==='machine_fs_read')this.read=definition;}};
39
+ registerMachineFsTools(server,{runtime:{}});
40
+ const args={root_id:'project',path:'large.bin',offset:PAGE+2,max_bytes:64,hash_file:false,timeout_ms:30000};
41
+ assert.equal(server.read.inputSchema.safeParse(args).success,true,'full tool rejects a valid next_offset');
42
+ assert.equal(machineFsGatewayInputSchema.safeParse({op:'read',...args}).success,true,'compact tool rejects a valid next_offset');
43
+ assert.equal(server.read.inputSchema.safeParse({...args,max_bytes:PAGE+1}).success,false,'per-call byte cap must remain');
44
+ assert.equal(machineFsGatewayInputSchema.safeParse({op:'read',...args,max_bytes:PAGE+1}).success,false);
45
+ assert.equal(server.read.inputSchema.safeParse({...args,offset:Number.MAX_SAFE_INTEGER+1}).success,false);
46
+ assert.equal(machineFsGatewayInputSchema.safeParse({op:'read',...args,offset:Number.MAX_SAFE_INTEGER+1}).success,false);
47
+ });
48
+
49
+ test('R64 reads page two using next_offset beyond 4 MiB',async t=>{
50
+ const f=await fixture(t);
51
+ const bytes=Buffer.alloc(PAGE+32,0x61);
52
+ bytes[0]=0x5a;
53
+ bytes[1]=0x5b;
54
+ bytes[PAGE+2]=0x7f;
55
+ await writeFile(path.join(f.project,'large.bin'),bytes);
56
+ const first=await f.runtime.read({rootId:'project',relativePath:'large.bin',offset:2,maxBytes:PAGE});
57
+ assert.equal(first.next_offset,PAGE+2);
58
+ assert.equal(first.eof,false);
59
+ const second=await f.runtime.read({rootId:'project',relativePath:'large.bin',offset:first.next_offset,maxBytes:64});
60
+ assert.equal(second.offset,PAGE+2);
61
+ assert.equal(Buffer.from(second.data_base64,'base64')[0],0x7f);
62
+ assert.equal(second.eof,true);
63
+ assert.equal(second.next_offset,bytes.length);
64
+ const atEof=await f.runtime.read({rootId:'project',relativePath:'large.bin',offset:bytes.length,maxBytes:1});
65
+ assert.equal(atEof.eof,true);
66
+ assert.equal(Buffer.from(atEof.data_base64,'base64').length,0);
67
+ assert.equal(atEof.next_offset,bytes.length);
68
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:bytes.length+1,maxBytes:1}),/exceeds file size/);
69
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:Number.MAX_SAFE_INTEGER+1,maxBytes:1}),/safe integer/);
70
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:0,maxBytes:PAGE+1}),/max_bytes/);
71
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:-PAGE-1,maxBytes:1}),/offset/);
72
+ });
73
+
74
+ test('R64 pages are independent observations and hash_file reveals replacement between calls',async t=>{
75
+ const f=await fixture(t);
76
+ const file=path.join(f.project,'large.bin');
77
+ const before=Buffer.alloc(PAGE+32,0x61);
78
+ const after=Buffer.alloc(PAGE+32,0x62);
79
+ await writeFile(file,before);
80
+ const first=await f.runtime.read({rootId:'project',relativePath:'large.bin',offset:2,maxBytes:PAGE,hashFile:true});
81
+ assert.equal(first.file_sha256,sha(before));
82
+ await writeFile(file,after);
83
+ const second=await f.runtime.read({rootId:'project',relativePath:'large.bin',offset:first.next_offset,maxBytes:64,hashFile:true});
84
+ assert.equal(second.file_sha256,sha(after));
85
+ assert.notEqual(second.file_sha256,first.file_sha256,'the caller must not treat these pages as one snapshot');
86
+ });
87
+
88
+ test('R64 a denied read root remains denied at a large offset',async t=>{
89
+ const f=await fixture(t,{read:false});
90
+ await writeFile(path.join(f.project,'large.bin'),Buffer.alloc(PAGE+16));
91
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:PAGE+1,maxBytes:1}),/does not allow read/);
92
+ });
93
+
94
+ test('R64 large offset does not bypass root containment',async t=>{
95
+ const f=await fixture(t);
96
+ await writeFile(path.join(f.root,'outside.bin'),Buffer.alloc(PAGE+16));
97
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'../outside.bin',offset:PAGE+1,maxBytes:1}),/relative|traversal|path|outside/i);
98
+ });
99
+
100
+ test('R64 large-offset read retains bounded worker cancellation',async t=>{
101
+ const f=await fixture(t);
102
+ await writeFile(path.join(f.project,'large.bin'),Buffer.alloc(PAGE+16));
103
+ const worker=path.join(f.root,'slow-read-worker.mjs');
104
+ await writeFile(worker,'setTimeout(() => process.stdout.write("{}"), 30000);\n');
105
+ const runtime=createMachineFsRuntime({policy:f.policy,signingKeyPath:f.keys.privateKeyPath,verifyKeyPath:f.keys.publicKeyPath,readWorkerPath:worker});
106
+ await assert.rejects(()=>runtime.read({rootId:'project',relativePath:'large.bin',offset:PAGE+1,maxBytes:1,timeoutMs:100}),/timed out after 100ms/);
107
+ });
108
+
109
+ test('R64 default hash stream is abort-bound to read timeout',async()=>{
110
+ const source=await readFile(new URL('../src/machine-fs.mjs',import.meta.url),'utf8');
111
+ assert.ok(/createReadStream\(file,\s*\{\s*signal\s*\}\)/.test(source),'hash stream must receive the read abort signal');
112
+ assert.ok(/abortController\.abort\(\)/.test(source),'read timeout must abort its hash stream');
113
+ });
114
+
115
+ test('R64 timed-out default hash stream receives abort and stops',async t=>{
116
+ const f=await fixture(t);
117
+ await writeFile(path.join(f.project,'large.bin'),Buffer.alloc(PAGE+16));
118
+ const original=fs.createReadStream;
119
+ let observedAbort=false;
120
+ fs.createReadStream=(_file,options={})=>{
121
+ const stream=new EventEmitter();
122
+ options.signal?.addEventListener('abort',()=>{
123
+ observedAbort=true;
124
+ queueMicrotask(()=>stream.emit('error',new Error('aborted')));
125
+ },{once:true});
126
+ return stream;
127
+ };
128
+ syncBuiltinESMExports();
129
+ try{
130
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:PAGE+1,maxBytes:1,hashFile:true,timeoutMs:100}),/timed out after 100ms/);
131
+ assert.equal(observedAbort,true,'default hash stream continued after timeout');
132
+ }finally{
133
+ fs.createReadStream=original;
134
+ syncBuiltinESMExports();
135
+ }
136
+ });
@@ -0,0 +1,51 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {readFile} from 'node:fs/promises';
4
+
5
+ const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
6
+ const json=async rel=>JSON.parse((await read(rel)).replace(/^\uFEFF/,''));
7
+ const sourceSha='d6f75feada9ad0ae2c248b3a833ac9cf0e04150d2430ddaa70b3dfb64a0b0a86';
8
+ const runtime={
9
+ release_id:'v0.15.39-3cda3b1c65b7b7c5',
10
+ manifest_sha256:'3cda3b1c65b7b7c561c5a8617156ab87d69cf162f447f3e99a4cb4a76471b3de',
11
+ generation_manifest_sha256:'f47cb96083679e764725df1bde6eda53169a39f55772c173ab22f89a1dfaa7ab'
12
+ };
13
+
14
+ test('R64 release identity distinguishes unsealed source predecessor from active runtime predecessor',async()=>{
15
+ const [pkg,lock,bridge,release,provenance,matrix,sbom,scope,gaps,version,gate]=await Promise.all([
16
+ json('package.json'),json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
17
+ json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),json('docs/R64-SCOPE.json'),
18
+ json('docs/R64-REFERENCE-GAP-MATRIX.json'),read('src/version.mjs'),read('scripts/gate-windows-r64-prepublish.ps1')
19
+ ]);
20
+ assert.equal(pkg.version,'0.15.41');
21
+ assert.equal(lock.version,pkg.version);
22
+ assert.equal(lock.packages[''].version,pkg.version);
23
+ assert.equal(bridge.version,pkg.version);
24
+ assert.match(version,/DEADBYTE_VERSION = '0\.15\.41'/);
25
+ assert.equal(release.version,pkg.version);
26
+ assert.equal(release.train,'R64');
27
+ assert.equal(provenance.version,pkg.version);
28
+ assert.equal(matrix.version,pkg.version);
29
+ assert.equal(matrix.train,'R64');
30
+ assert.equal(sbom.metadata.component.version,pkg.version);
31
+ assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r64:0.15.41');
32
+ assert.deepEqual(release.runtime_predecessor,runtime);
33
+ assert.deepEqual(provenance.runtime_predecessor,runtime);
34
+ assert.equal(release.source_predecessor.version,'0.15.40');
35
+ assert.equal(release.source_predecessor.manifest_file_sha256,sourceSha);
36
+ assert.equal(release.source_predecessor.release_status,'NOT_PROVEN_RELEASED');
37
+ assert.equal(provenance.source_predecessor_manifest_file_sha256,sourceSha);
38
+ assert.equal(scope.source_predecessor.manifest_sha256,sourceSha);
39
+ assert.deepEqual(scope.runtime_predecessor,runtime);
40
+ assert.equal(release.r64_bounded_large_file_read.new_public_tools,0);
41
+ assert.equal(release.r64_bounded_large_file_read.new_authority_scopes,0);
42
+ assert.equal(release.r64_bounded_large_file_read.cross_page_atomic_snapshot_claim,false);
43
+ assert.equal(matrix.r64.prepublish_only,true);
44
+ assert.equal(gaps.references.length,7);
45
+ assert.equal(gaps.references.filter(row=>row.proposed_action.startsWith('ADAPT')).length,1);
46
+ assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r64-prepublish.ps1');
47
+ assert.match(pkg.scripts['r64:focused:test'],/r64-machine-fs-large-read\.test\.mjs/);
48
+ assert.match(gate,/d6f75feada9ad0ae2c248b3a833ac9cf0e04150d2430ddaa70b3dfb64a0b0a86/);
49
+ assert.match(gate,/v0\.15\.39-3cda3b1c65b7b7c5/);
50
+ assert.doesNotMatch(gate,/npm\.cmd publish|--publish-only/);
51
+ });
@@ -1,5 +1,6 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
+ import { createHash } from 'node:crypto';
3
4
  import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
4
5
  import os from 'node:os';
5
6
  import path from 'node:path';
@@ -645,13 +646,14 @@ winTest('explicit remote status remains a one-shot controller command',async()=>
645
646
  }finally{await rm(fx.dir,{recursive:true,force:true});}
646
647
  });
647
648
 
648
- winTest('explicit remote status reports CLI package and active runtime VERSION SKEW',async()=>{
649
+ winTest('explicit remote status keeps the coherent runtime one-shot and silent',async()=>{
649
650
  const fx=await fixture({statusOnline:true});
650
651
  try{
651
- const manifest='1'.repeat(64),generation='2'.repeat(64),launcher='3'.repeat(64);
652
+ const manifest=createHash('sha256').update(await readFile(path.join(root,'MANIFEST.SHA256'))).digest('hex');
653
+ const generation='2'.repeat(64),launcher='3'.repeat(64);
652
654
  await writeFile(path.join(fx.state,'active-release.json'),JSON.stringify({
653
- schema:'deadbyte.active-release.v1',release_id:`v0.15.16-${manifest.slice(0,16)}`,version:'0.15.16',manifest_sha256:manifest,
654
- release_root:'C:/deadbyte/releases/0.15.16',generation_root:'C:/deadbyte/generations/0.15.16',generation_manifest_sha256:generation,
655
+ schema:'deadbyte.active-release.v1',release_id:`v${DEADBYTE_VERSION}-${manifest.slice(0,16)}`,version:DEADBYTE_VERSION,manifest_sha256:manifest,
656
+ release_root:'C:/deadbyte/releases/current',generation_root:'C:/deadbyte/generations/current',generation_manifest_sha256:generation,
655
657
  launcher_sha256:launcher,config_path:'C:/deadbyte/config.psd1'
656
658
  }),'utf8');
657
659
  const child=spawn(process.execPath,[cliPath,'remote','status'],{env:fx.env,stdio:['ignore','pipe','pipe'],windowsHide:true});
@@ -659,7 +661,7 @@ winTest('explicit remote status reports CLI package and active runtime VERSION S
659
661
  const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
660
662
  assert.equal(ended.timeout,undefined);
661
663
  assert.equal(ended.code,0,output.stderr);
662
- assert.ok(output.stderr.includes(`VERSION SKEW: CLI package ${DEADBYTE_VERSION}; active runtime 0.15.16`),output.stderr);
664
+ assert.doesNotMatch(output.stderr,/VERSION SKEW/);
663
665
  assert.deepEqual(await traceCommands(fx.trace),['status']);
664
666
  }finally{await rm(fx.dir,{recursive:true,force:true});}
665
667
  });