deadbyte-mcp 0.15.74 → 0.15.76
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.
- package/MANIFEST.SHA256 +108 -42
- package/PROVENANCE.json +20 -22
- package/README.txt +23 -18
- package/RELEASE.json +69 -18
- package/SBOM.cdx.json +2 -2
- package/TEST-MATRIX.json +32 -2
- package/bin/deadbyte-desktop-uia-r199-fixed.exe +0 -0
- package/bin/deadbyte-desktop-uia-r199-fixed.obj +0 -0
- package/bin/deadbyte-desktop-uia-r199.exe +0 -0
- package/bin/deadbyte-desktop-uia-r199.obj +0 -0
- package/bin/deadbyte-fs-read-r197-fixed.exe +0 -0
- package/bin/deadbyte-fs-read-r198.exe +0 -0
- package/bin/deadbyte-fs-read-r198.obj +0 -0
- package/bin/deadbyte-root-relative-probe-r197.exe +0 -0
- package/bridge/package.json +1 -1
- package/controller/deadbyte-process-policy.json +4 -4
- package/docs/R184-package-lock.json +2 -8
- package/native/deadbyte-desktop-uia-r199.cpp +345 -0
- package/native/deadbyte-fs-read-r197.cpp +174 -0
- package/native/deadbyte-fs-read-r198.cpp +181 -0
- package/native/deadbyte-root-relative-probe-r197.cpp +97 -0
- package/package.json +5 -2
- package/scripts/build-native-desktop-uia-r199-fixed.ps1 +28 -0
- package/scripts/build-native-desktop-uia-r199.ps1 +28 -0
- package/scripts/build-native-fs-read-r197-fixed.ps1 +28 -0
- package/scripts/build-native-fs-read-r197.ps1 +28 -0
- package/scripts/build-native-fs-read-r198.ps1 +28 -0
- package/scripts/build-native-root-probe-r197.ps1 +28 -0
- package/scripts/gate-windows-r195.ps1 +114 -0
- package/scripts/gate-windows-r206.ps1 +116 -0
- package/scripts/gate-windows-r207.ps1 +104 -0
- package/scripts/init-desktop-policy-r199.ps1 +85 -0
- package/scripts/npm-release-r48.mjs +27 -0
- package/scripts/npm-release-readiness-r195.mjs +72 -0
- package/scripts/npm-release-readiness-r206.mjs +76 -0
- package/scripts/npm-release-readiness-r207.mjs +76 -0
- package/scripts/r193-owner-request-live.mjs +8 -7
- package/scripts/r193-owner-uac-broker.mjs +6 -5
- package/scripts/r205-candidate-selection.mjs +22 -0
- package/src/candidate-selection-evidence-r206.mjs +71 -0
- package/src/candidate-selection-r205.mjs +96 -0
- package/src/desktop-postcondition-r196.mjs +30 -0
- package/src/desktop-runtime-r40.mjs +44 -7
- package/src/desktop-uia-identity-r199.mjs +51 -0
- package/src/desktop-uia-r40.mjs +9 -1
- package/src/machine-fs-handle-read-r196.mjs +43 -0
- package/src/machine-fs-native-read-r197.mjs +73 -0
- package/src/machine-fs-native-read-r198.mjs +76 -0
- package/src/machine-fs-read-worker.mjs +5 -25
- package/src/machine-fs.mjs +31 -16
- package/src/r195-canonical-owner-observation.mjs +15 -0
- package/src/r207-owner-enrollment-io.mjs +30 -0
- package/src/remote-destination-journal-r202.mjs +120 -0
- package/src/remote-device-r44.mjs +89 -14
- package/src/remote-payload-boundary-r201.mjs +71 -0
- package/src/remote-terminal-evidence-r200.mjs +60 -0
- package/src/version.mjs +1 -1
- package/test/desktop-runtime-r40.test.mjs +111 -0
- package/test/desktop-uia-r40.test.mjs +15 -0
- package/test/fixtures/r197-junction-swap-worker.mjs +21 -0
- package/test/fixtures/r203-journal-writer.mjs +6 -0
- package/test/process-policy-refresh.test.mjs +4 -4
- package/test/r130-release-security-contract.test.mjs +8 -8
- package/test/r132-release-identity.test.mjs +7 -7
- package/test/r153-prepublish-identity.test.mjs +1 -1
- package/test/r160-release-contract.test.mjs +3 -3
- package/test/r165-live-cli-skew.test.mjs +1 -1
- package/test/r167-release-contract.test.mjs +11 -11
- package/test/r168-release-contract.test.mjs +4 -4
- package/test/r172-release-contract.test.mjs +6 -6
- package/test/r173-release-contract.test.mjs +16 -16
- package/test/r179-release-contract.test.mjs +12 -12
- package/test/r190-release-contract.test.mjs +10 -10
- package/test/r191-release-contract.test.mjs +12 -12
- package/test/r192-release-identity.test.mjs +9 -9
- package/test/r193-release-identity.test.mjs +24 -22
- package/test/r193-release-readiness.test.mjs +2 -2
- package/test/r193-windows-gate.test.mjs +10 -10
- package/test/r194-release-identity.test.mjs +19 -15
- package/test/r194-release-readiness.test.mjs +3 -3
- package/test/r194-windows-gate.test.mjs +9 -8
- package/test/r195-canonical-owner-observation.test.mjs +32 -0
- package/test/r195-release-readiness.test.mjs +22 -0
- package/test/r196-desktop-postcondition.test.mjs +53 -0
- package/test/r196-handle-bound-read.test.mjs +99 -0
- package/test/r196-remote-outcome.test.mjs +94 -0
- package/test/r197-namespace-race.test.mjs +41 -0
- package/test/r197-native-dispatch-race.test.mjs +49 -0
- package/test/r197-native-file-read.test.mjs +60 -0
- package/test/r197-native-root-open.test.mjs +61 -0
- package/test/r198-root-identity.test.mjs +88 -0
- package/test/r199-native-uia-worker.test.mjs +28 -0
- package/test/r199-uia-identity.test.mjs +43 -0
- package/test/r200-remote-reconcile.test.mjs +106 -0
- package/test/r201-payload-boundary.test.mjs +78 -0
- package/test/r201-payload-fuzz.test.mjs +37 -0
- package/test/r201-tool-boundary-fuzz.test.mjs +120 -0
- package/test/r202-destination-journal.test.mjs +92 -0
- package/test/r203-atomic-journal.test.mjs +86 -0
- package/test/r205-candidate-selection-cli.test.mjs +31 -0
- package/test/r205-candidate-selection.test.mjs +83 -0
- package/test/r206-candidate-evidence.test.mjs +64 -0
- package/test/r206-release-contract.test.mjs +42 -0
- package/test/r206-release-readiness.test.mjs +23 -0
- package/test/r207-owner-enrollment-io.test.mjs +37 -0
- package/test/r207-release-contract.test.mjs +51 -0
- package/test/r207-release-readiness.test.mjs +23 -0
- package/test/r59-tool-surface-compat.test.mjs +1 -1
- package/test/r64-machine-fs-large-read.test.mjs +26 -12
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { canonicalJson } from '../src/canonical-json.mjs';
|
|
5
|
+
import { verifyCandidateSelectionEvidenceR206 } from '../src/candidate-selection-evidence-r206.mjs';
|
|
6
|
+
|
|
7
|
+
const H=c=>c.repeat(64);
|
|
8
|
+
const fixture=H('a'),environment=H('b');
|
|
9
|
+
const sha=value=>createHash('sha256').update(Buffer.from(canonicalJson(value),'utf8')).digest('hex');
|
|
10
|
+
const samples={baseline:[100,100,100,100,100,100,100],candidate:[75,75,75,75,75,75,75]};
|
|
11
|
+
const input=()=>({
|
|
12
|
+
schema:'deadbyte.candidate-selection.r205.v1',fixture_sha256:fixture,environment_sha256:environment,
|
|
13
|
+
baseline:{artifact_sha256:H('1'),correctness:{status:'PASS',artifact_sha256:H('1'),fixture_sha256:fixture,receipt_sha256:H('2')},
|
|
14
|
+
benchmark:{artifact_sha256:H('1'),fixture_sha256:fixture,environment_sha256:environment,receipt_sha256:H('3'),samples_ms:samples.baseline}},
|
|
15
|
+
candidates:[{candidate_id:'candidate',artifact_sha256:H('4'),
|
|
16
|
+
correctness:{status:'PASS',artifact_sha256:H('4'),fixture_sha256:fixture,receipt_sha256:H('5')},
|
|
17
|
+
benchmark:{artifact_sha256:H('4'),fixture_sha256:fixture,environment_sha256:environment,receipt_sha256:H('6'),samples_ms:samples.candidate}}]
|
|
18
|
+
});
|
|
19
|
+
const receipts=()=>new Map([
|
|
20
|
+
[H('2'),{verified:true,receipt_sha256:H('2'),evidence_kind:'correctness',signer_role:'independent_correctness_oracle',artifact_sha256:H('1'),fixture_sha256:fixture,status:'PASS'}],
|
|
21
|
+
[H('3'),{verified:true,receipt_sha256:H('3'),evidence_kind:'benchmark',signer_role:'independent_benchmark_runner',artifact_sha256:H('1'),fixture_sha256:fixture,environment_sha256:environment,samples_sha256:sha(samples.baseline)}],
|
|
22
|
+
[H('5'),{verified:true,receipt_sha256:H('5'),evidence_kind:'correctness',signer_role:'independent_correctness_oracle',artifact_sha256:H('4'),fixture_sha256:fixture,status:'PASS'}],
|
|
23
|
+
[H('6'),{verified:true,receipt_sha256:H('6'),evidence_kind:'benchmark',signer_role:'independent_benchmark_runner',artifact_sha256:H('4'),fixture_sha256:fixture,environment_sha256:environment,samples_sha256:sha(samples.candidate)}]
|
|
24
|
+
]);
|
|
25
|
+
const verifier=map=>async receiptSha=>map.get(receiptSha)??{verified:false,receipt_sha256:receiptSha};
|
|
26
|
+
|
|
27
|
+
test('R206 independently verifies every decision-bearing receipt but never authorizes release',async()=>{
|
|
28
|
+
const result=await verifyCandidateSelectionEvidenceR206(input(),{verifyReceipt:verifier(receipts())});
|
|
29
|
+
assert.equal(result.state,'PROVISIONAL_CANDIDATE');
|
|
30
|
+
assert.equal(result.evidence_verified,true);
|
|
31
|
+
assert.equal(result.verified_receipt_count,4);
|
|
32
|
+
assert.equal(result.release_authorized,false);
|
|
33
|
+
assert.match(result.evidence_binding_sha256,/^[0-9a-f]{64}$/);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('R206 rejects a forged or unverifiable receipt',async()=>{
|
|
37
|
+
const map=receipts();map.set(H('5'),{...map.get(H('5')),verified:false});
|
|
38
|
+
await assert.rejects(()=>verifyCandidateSelectionEvidenceR206(input(),{verifyReceipt:verifier(map)}),/receipt verification failed/);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('R206 rejects correctness status or artifact drift after grading',async()=>{
|
|
42
|
+
for(const change of [{status:'FAIL'},{artifact_sha256:H('7')}]){
|
|
43
|
+
const map=receipts();map.set(H('5'),{...map.get(H('5')),...change});
|
|
44
|
+
await assert.rejects(()=>verifyCandidateSelectionEvidenceR206(input(),{verifyReceipt:verifier(map)}),/correctness receipt binding mismatch/);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('R206 rejects benchmark sample or environment drift',async()=>{
|
|
49
|
+
for(const change of [{samples_sha256:H('7')},{environment_sha256:H('7')}]){
|
|
50
|
+
const map=receipts();map.set(H('6'),{...map.get(H('6')),...change});
|
|
51
|
+
await assert.rejects(()=>verifyCandidateSelectionEvidenceR206(input(),{verifyReceipt:verifier(map)}),/benchmark receipt binding mismatch/);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('R206 rejects proposer-controlled signer roles and receipt reuse',async()=>{
|
|
56
|
+
const proposer=receipts();proposer.set(H('5'),{...proposer.get(H('5')),signer_role:'candidate_proposer'});
|
|
57
|
+
await assert.rejects(()=>verifyCandidateSelectionEvidenceR206(input(),{verifyReceipt:verifier(proposer)}),/correctness receipt binding mismatch/);
|
|
58
|
+
const reused=input();reused.candidates[0].correctness.receipt_sha256=H('2');
|
|
59
|
+
await assert.rejects(()=>verifyCandidateSelectionEvidenceR206(reused,{verifyReceipt:verifier(receipts())}),/receipt reused/);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('R206 refuses a missing verifier instead of trusting hash-shaped claims',async()=>{
|
|
63
|
+
await assert.rejects(()=>verifyCandidateSelectionEvidenceR206(input(),{}),/independent receipt verifier required/);
|
|
64
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
|
|
7
|
+
const root=path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
|
8
|
+
const json=async name=>JSON.parse(await readFile(path.join(root,name),'utf8'));
|
|
9
|
+
|
|
10
|
+
test('R207 retains R206 evidence while binding R206 source separately from active 0.15.75 runtime',async()=>{
|
|
11
|
+
const [pkg,lock,bridge,release,provenance,matrix,sbom]=await Promise.all([
|
|
12
|
+
json('package.json'),json('docs/R184-package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
|
|
13
|
+
json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json')
|
|
14
|
+
]);
|
|
15
|
+
assert.equal(pkg.version,'0.15.76');
|
|
16
|
+
assert.equal(lock.version,'0.15.76');
|
|
17
|
+
assert.equal(lock.packages[''].version,'0.15.76');
|
|
18
|
+
assert.equal(bridge.version,'0.15.76');
|
|
19
|
+
assert.equal(release.version,'0.15.76');assert.equal(release.train,'R207');
|
|
20
|
+
assert.equal(release.source_predecessor.train,'R206');
|
|
21
|
+
assert.equal(release.source_predecessor.manifest_sha256,'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248');
|
|
22
|
+
assert.equal(release.runtime_predecessor.release_id,'v0.15.75-9039fff265696091');
|
|
23
|
+
assert.equal(provenance.builder,'deadbyte-r207-owner-enrollment-fix');
|
|
24
|
+
assert.equal(provenance.source_predecessor_train,'R206');
|
|
25
|
+
assert.equal(provenance.source_predecessor_manifest_sha256,'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248');
|
|
26
|
+
assert.equal(matrix.train,'R207');
|
|
27
|
+
assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r207:0.15.76');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('R206 release contract keeps public surface stable and deferred work truthful',async()=>{
|
|
31
|
+
const release=await json('RELEASE.json');
|
|
32
|
+
assert.equal(release.capabilities.compact_tool_count,43);
|
|
33
|
+
assert.equal(release.capabilities.full_tool_count,117);
|
|
34
|
+
assert.equal(release.r206.public_tool_delta,0);
|
|
35
|
+
assert.equal(release.r206.authority_scope_delta,0);
|
|
36
|
+
assert.equal(release.r206.selector_release_authority,false);
|
|
37
|
+
assert.deepEqual(release.r206.deferred_unverified,[
|
|
38
|
+
'REMOTE_TWO_MACHINE_E2E','NATIVE_UIA_APPLICATION_EFFECT','BOUNDED_CDP_HARNESS2','REA_WINDOWS_209_TOOL_PARITY'
|
|
39
|
+
]);
|
|
40
|
+
assert.equal(release.r206.npm_publish,'NOT_RUN');
|
|
41
|
+
assert.equal(release.r206.production_activation,'NOT_RUN');
|
|
42
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {assertR206NpmPublishReady,assertR206PackedIdentity} from '../scripts/npm-release-readiness-r206.mjs';
|
|
4
|
+
|
|
5
|
+
const release={
|
|
6
|
+
version:'0.15.75',train:'R206',
|
|
7
|
+
parent:{version:'0.15.74',release_id:'v0.15.74-e84bf4eed16e9443',
|
|
8
|
+
manifest_sha256:'e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47',
|
|
9
|
+
generation_manifest_sha256:'598f896be9ce65e6b0c618e8c8f6eaa2a9d91617a76a146bf3deb385a56d19e7'},
|
|
10
|
+
source_predecessor:{train:'R205',manifest_sha256:'166eebde18d53a9ec46f738383c289733f9cd37918b3572b7515d1ab9b122c92'},
|
|
11
|
+
r206:{scope:'EVIDENCE_BOUND_CANDIDATE_SELECTION_RELEASE_CLOSURE',public_tool_delta:0,authority_scope_delta:0,selector_release_authority:false}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
test('R206 publication refuses an absent exact-byte closure before pack or registry effects',async()=>{
|
|
15
|
+
await assert.rejects(assertR206NpmPublishReady(release,{root:'D:\\candidate'}),/PUBLISH_BLOCKED R206.*closure root absent/);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('R206 packed identity refuses any artifact differing from the protected closure',()=>{
|
|
19
|
+
assert.throws(()=>assertR206PackedIdentity({
|
|
20
|
+
tarball_sha256:'a'.repeat(64),tarball_integrity:'sha512-expected',tarball_shasum:'b'.repeat(40),
|
|
21
|
+
observedSha256:'c'.repeat(64),observedIntegrity:'sha512-other',observedShasum:'d'.repeat(40)
|
|
22
|
+
}),/PUBLISH_BLOCKED R206.*repacked tarball/);
|
|
23
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {mkdtemp,mkdir,readFile,rm,symlink,writeFile} from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import {ensureOwnerConsentDirectory,parseOwnerEnrollmentJson} from '../src/r207-owner-enrollment-io.mjs';
|
|
7
|
+
|
|
8
|
+
test('R207 parses Windows PowerShell UTF-8 BOM supervisor ledgers',()=>{
|
|
9
|
+
const value=parseOwnerEnrollmentJson(Buffer.concat([Buffer.from([0xef,0xbb,0xbf]),Buffer.from('{"schema":"deadbyte.supervisor.instance.v1","pid":17}')]),'supervisor ledger');
|
|
10
|
+
assert.equal(value.schema,'deadbyte.supervisor.instance.v1');
|
|
11
|
+
assert.equal(value.pid,17);
|
|
12
|
+
assert.throws(()=>parseOwnerEnrollmentJson(Buffer.from('\uFEFF[]'),'supervisor ledger'),/must be an object/);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('R207 initializes the bounded owner-consent state directory before no-clobber request creation',async()=>{
|
|
16
|
+
const base=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r207-owner-'));
|
|
17
|
+
try{
|
|
18
|
+
const runtime=path.join(base,'runtime');await mkdir(runtime);
|
|
19
|
+
const consent=await ensureOwnerConsentDirectory(runtime);
|
|
20
|
+
assert.equal(consent.toLowerCase(),path.join(runtime,'owner-consent').toLowerCase());
|
|
21
|
+
const request=path.join(consent,'request.json');
|
|
22
|
+
await writeFile(request,'{}\n',{flag:'wx'});
|
|
23
|
+
await assert.rejects(writeFile(request,'{}\n',{flag:'wx'}),error=>error?.code==='EEXIST');
|
|
24
|
+
assert.equal(await readFile(request,'utf8'),'{}\n');
|
|
25
|
+
}finally{await rm(base,{recursive:true,force:true});}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('R207 rejects an owner-consent junction or symlink escape',async t=>{
|
|
29
|
+
const base=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r207-owner-link-'));
|
|
30
|
+
try{
|
|
31
|
+
const runtime=path.join(base,'runtime'),outside=path.join(base,'outside');
|
|
32
|
+
await mkdir(runtime);await mkdir(outside);
|
|
33
|
+
try{await symlink(outside,path.join(runtime,'owner-consent'),process.platform==='win32'?'junction':'dir');}
|
|
34
|
+
catch(error){if(error?.code==='EPERM'){t.skip('Windows symlink privilege unavailable');return;}throw error;}
|
|
35
|
+
await assert.rejects(ensureOwnerConsentDirectory(runtime),/real directory|escapes/);
|
|
36
|
+
}finally{await rm(base,{recursive:true,force:true});}
|
|
37
|
+
});
|
|
@@ -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 root = new URL('../', import.meta.url);
|
|
6
|
+
const json = async name => JSON.parse(await readFile(new URL(name, root), 'utf8'));
|
|
7
|
+
|
|
8
|
+
test('R207 identity binds exact R206 source and active 0.15.75 runtime predecessors', async () => {
|
|
9
|
+
const [pkg, lock, bridge, release, provenance, matrix, sbom, versionSource] = await Promise.all([
|
|
10
|
+
json('package.json'), json('docs/R184-package-lock.json'), json('bridge/package.json'), json('RELEASE.json'),
|
|
11
|
+
json('PROVENANCE.json'), json('TEST-MATRIX.json'), json('SBOM.cdx.json'),
|
|
12
|
+
readFile(new URL('src/version.mjs', root), 'utf8')
|
|
13
|
+
]);
|
|
14
|
+
for (const value of [pkg.version, lock.version, lock.packages[''].version, bridge.version,
|
|
15
|
+
release.version, provenance.version, matrix.version, sbom.metadata.component.version]) {
|
|
16
|
+
assert.equal(value, '0.15.76');
|
|
17
|
+
}
|
|
18
|
+
assert.match(versionSource, /DEADBYTE_VERSION = '0\.15\.76'/);
|
|
19
|
+
assert.equal(release.train, 'R207');
|
|
20
|
+
assert.equal(matrix.train, 'R207');
|
|
21
|
+
assert.equal(sbom.serialNumber, 'urn:cdx:deadbyte-mcp:r207:0.15.76');
|
|
22
|
+
assert.deepEqual(release.source_predecessor, {
|
|
23
|
+
version: '0.15.75',
|
|
24
|
+
train: 'R206',
|
|
25
|
+
source_path: 'D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.75-r206-release-closure',
|
|
26
|
+
release_status: 'RELEASED',
|
|
27
|
+
manifest_status: 'R206_MANIFEST_VERIFIED',
|
|
28
|
+
manifest_sha256: '9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248',
|
|
29
|
+
tarball_sha256: 'c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9'
|
|
30
|
+
});
|
|
31
|
+
assert.deepEqual(release.runtime_predecessor, {
|
|
32
|
+
version: '0.15.75',
|
|
33
|
+
release_id: 'v0.15.75-9039fff265696091',
|
|
34
|
+
manifest_sha256: '9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248',
|
|
35
|
+
generation_manifest_sha256: '83a212e01173c73f78cff2a6d26e6f3f50f476a8c0ea3cbbf592a466071909e9'
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('R207 keeps authority surface stable and fixes only protected owner-enrollment IO', async () => {
|
|
40
|
+
const release = await json('RELEASE.json');
|
|
41
|
+
assert.equal(release.capabilities.compact_tool_count, 43);
|
|
42
|
+
assert.equal(release.capabilities.full_tool_count, 117);
|
|
43
|
+
assert.equal(release.r207.scope, 'PROTECTED_OWNER_ENROLLMENT_IO_RECOVERY');
|
|
44
|
+
assert.equal(release.r207.public_tool_delta, 0);
|
|
45
|
+
assert.equal(release.r207.authority_scope_delta, 0);
|
|
46
|
+
assert.equal(release.r207.r70_weakened, false);
|
|
47
|
+
assert.equal(release.r207.r89_weakened, false);
|
|
48
|
+
assert.equal(release.r207.owner_private_key_access, false);
|
|
49
|
+
assert.equal(release.r207.owner_consent_directory_initialization, 'FAIL_CLOSED_CONTAINED_NON_REPARSE');
|
|
50
|
+
assert.equal(release.r207.supervisor_ledger_utf8_bom, 'ACCEPT_ONE_LEADING_BOM_ONLY');
|
|
51
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {assertR207NpmPublishReady,assertR207PackedIdentity} from '../scripts/npm-release-readiness-r207.mjs';
|
|
4
|
+
const base={version:'0.15.76',train:'R207',
|
|
5
|
+
parent:{version:'0.15.75',release_id:'v0.15.75-9039fff265696091',manifest_sha256:'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248',generation_manifest_sha256:'83a212e01173c73f78cff2a6d26e6f3f50f476a8c0ea3cbbf592a466071909e9'},
|
|
6
|
+
source_predecessor:{train:'R206',manifest_sha256:'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248'},
|
|
7
|
+
r207:{scope:'PROTECTED_OWNER_ENROLLMENT_IO_RECOVERY',public_tool_delta:0,authority_scope_delta:0,owner_private_key_access:false,r70_weakened:false,r89_weakened:false}};
|
|
8
|
+
test('R207 refuses publish absent independently verified closure',async()=>{
|
|
9
|
+
await assert.rejects(assertR207NpmPublishReady(base,{root:'D:\\candidate'}),/PUBLISH_BLOCKED R207.*closure root absent/);
|
|
10
|
+
});
|
|
11
|
+
test('R207 refuses any authority increase or private-key access',async()=>{
|
|
12
|
+
for(const key of ['owner_private_key_access','r70_weakened','r89_weakened']){
|
|
13
|
+
const altered=structuredClone(base);altered.r207[key]=true;
|
|
14
|
+
await assert.rejects(assertR207NpmPublishReady(altered,{root:'D:\\candidate'}),/PUBLISH_BLOCKED R207.*public authority surface widened/);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
test('R207 rejects mismatched parent release before reading any closure',async()=>{
|
|
18
|
+
const altered=structuredClone(base);altered.parent.release_id='v0.15.74-e84bf4eed16e9443';
|
|
19
|
+
await assert.rejects(assertR207NpmPublishReady(altered,{root:'D:\\candidate'}),/PUBLISH_BLOCKED R207.*lineage mismatch/);
|
|
20
|
+
});
|
|
21
|
+
test('R207 refuses repacked artifact identity drift',()=>{
|
|
22
|
+
assert.throws(()=>assertR207PackedIdentity({tarball_sha256:'a'.repeat(64),tarball_integrity:'sha512-proof',tarball_shasum:'b'.repeat(40),observedSha256:'c'.repeat(64),observedIntegrity:'sha512-another',observedShasum:'d'.repeat(40)}),/PUBLISH_BLOCKED R207.*repacked tarball/);
|
|
23
|
+
});
|
|
@@ -83,7 +83,7 @@ test('R72 compact baseline permits only R64 read offset and authorized coding-on
|
|
|
83
83
|
assert.deepEqual(diff.added,[]);
|
|
84
84
|
assert.deepEqual(diff.removed,[]);
|
|
85
85
|
const packageVersion=JSON.parse(await readFile(path.join(repoRoot,'package.json'),'utf8')).version;
|
|
86
|
-
if(['0.15.41','0.15.42','0.15.43','0.15.44','0.15.45','0.15.46','0.15.47','0.15.48','0.15.49','0.15.50','0.15.51','0.15.52','0.15.53','0.15.54','0.15.55','0.15.56','0.15.57','0.15.58','0.15.59','0.15.60','0.15.61','0.15.62','0.15.63','0.15.64','0.15.65','0.15.66','0.15.67','0.15.68','0.15.69','0.15.70','0.15.71','0.15.72','0.15.73','0.15.74'].includes(packageVersion)){
|
|
86
|
+
if(['0.15.41','0.15.42','0.15.43','0.15.44','0.15.45','0.15.46','0.15.47','0.15.48','0.15.49','0.15.50','0.15.51','0.15.52','0.15.53','0.15.54','0.15.55','0.15.56','0.15.57','0.15.58','0.15.59','0.15.60','0.15.61','0.15.62','0.15.63','0.15.64','0.15.65','0.15.66','0.15.67','0.15.68','0.15.69','0.15.70','0.15.71','0.15.72','0.15.73','0.15.74','0.15.75','0.15.76'].includes(packageVersion)){
|
|
87
87
|
assert.deepEqual([...diff.schema_changed].sort(),['machine_fs','native_diff_preview']);
|
|
88
88
|
assert.equal(diff.unchanged.length,41);
|
|
89
89
|
const prior=baseline.tools.find(tool=>tool.name==='machine_fs');
|
|
@@ -9,6 +9,7 @@ import {tmpdir} from 'node:os';
|
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import {loadCodingPolicy} from '../src/coding-plane.mjs';
|
|
11
11
|
import {createMachineFsRuntime} from '../src/machine-fs.mjs';
|
|
12
|
+
import {readRangeFromHandle} from '../src/machine-fs-handle-read-r196.mjs';
|
|
12
13
|
import {generateTrustKeypair} from '../src/trust.mjs';
|
|
13
14
|
import {machineFsGatewayInputSchema} from '../src/compact-gateway-mcp-tools.mjs';
|
|
14
15
|
import {registerMachineFsTools} from '../src/machine-fs-mcp-tools.mjs';
|
|
@@ -106,31 +107,44 @@ test('R64 large-offset read retains bounded worker cancellation',async t=>{
|
|
|
106
107
|
await assert.rejects(()=>runtime.read({rootId:'project',relativePath:'large.bin',offset:PAGE+1,maxBytes:1,timeoutMs:100}),/timed out after 100ms/);
|
|
107
108
|
});
|
|
108
109
|
|
|
109
|
-
test('R64 default hash stream
|
|
110
|
+
test('R64 default hash stream uses the retained handle and remains abort-bound',async()=>{
|
|
110
111
|
const source=await readFile(new URL('../src/machine-fs.mjs',import.meta.url),'utf8');
|
|
111
|
-
|
|
112
|
+
const handleSource=await readFile(new URL('../src/machine-fs-handle-read-r196.mjs',import.meta.url),'utf8');
|
|
113
|
+
assert.ok(/readRangeFromHandle\(handle,/.test(source),'read must use opened handle');
|
|
114
|
+
assert.ok(/handle\.createReadStream\(\{start:0,autoClose:false,signal\}\)/.test(handleSource),
|
|
115
|
+
'hash must stream through the retained FileHandle with abort signal');
|
|
112
116
|
assert.ok(/abortController\.abort\(\)/.test(source),'read timeout must abort its hash stream');
|
|
113
117
|
});
|
|
114
118
|
|
|
115
|
-
test('R64
|
|
119
|
+
test('R64 fallback FileHandle hash stream obeys abort independently of the new native backend',async t=>{
|
|
116
120
|
const f=await fixture(t);
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
+
const file=path.join(f.project,'large.bin');
|
|
122
|
+
await writeFile(file,Buffer.alloc(PAGE+16));
|
|
123
|
+
const handle=await fs.promises.open(file,'r');
|
|
124
|
+
const proto=Object.getPrototypeOf(handle);
|
|
125
|
+
const original=proto.createReadStream;
|
|
126
|
+
let started,called=false,observedAbort=false;
|
|
127
|
+
const entered=new Promise(resolve=>started=resolve);
|
|
128
|
+
proto.createReadStream=function(options={}){
|
|
129
|
+
called=true;
|
|
121
130
|
const stream=new EventEmitter();
|
|
122
131
|
options.signal?.addEventListener('abort',()=>{
|
|
123
132
|
observedAbort=true;
|
|
124
133
|
queueMicrotask(()=>stream.emit('error',new Error('aborted')));
|
|
125
134
|
},{once:true});
|
|
135
|
+
started();
|
|
126
136
|
return stream;
|
|
127
137
|
};
|
|
128
|
-
|
|
138
|
+
const controller=new AbortController();
|
|
129
139
|
try{
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
const operation=readRangeFromHandle(handle,{offset:PAGE+1,length:1,hashFile:true,signal:controller.signal});
|
|
141
|
+
await entered;
|
|
142
|
+
controller.abort();
|
|
143
|
+
await assert.rejects(operation,/aborted/);
|
|
144
|
+
assert.equal(called,true,'fallback handle hash was not started');
|
|
145
|
+
assert.equal(observedAbort,true,'fallback hash stream ignored abort');
|
|
132
146
|
}finally{
|
|
133
|
-
|
|
134
|
-
|
|
147
|
+
proto.createReadStream=original;
|
|
148
|
+
await handle.close();
|
|
135
149
|
}
|
|
136
150
|
});
|