deadbyte-mcp 0.15.75 → 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.
Files changed (42) hide show
  1. package/MANIFEST.SHA256 +41 -35
  2. package/PROVENANCE.json +17 -17
  3. package/README.txt +12 -12
  4. package/RELEASE.json +35 -17
  5. package/SBOM.cdx.json +2 -2
  6. package/TEST-MATRIX.json +12 -2
  7. package/bridge/package.json +1 -1
  8. package/controller/deadbyte-process-policy.json +4 -4
  9. package/docs/R184-package-lock.json +2 -2
  10. package/package.json +3 -2
  11. package/scripts/gate-windows-r207.ps1 +104 -0
  12. package/scripts/npm-release-r48.mjs +10 -0
  13. package/scripts/npm-release-readiness-r207.mjs +76 -0
  14. package/scripts/r193-owner-request-live.mjs +3 -1
  15. package/scripts/r193-owner-uac-broker.mjs +3 -2
  16. package/src/r207-owner-enrollment-io.mjs +30 -0
  17. package/src/version.mjs +1 -1
  18. package/test/process-policy-refresh.test.mjs +4 -4
  19. package/test/r130-release-security-contract.test.mjs +7 -7
  20. package/test/r132-release-identity.test.mjs +6 -6
  21. package/test/r153-prepublish-identity.test.mjs +1 -1
  22. package/test/r160-release-contract.test.mjs +3 -3
  23. package/test/r165-live-cli-skew.test.mjs +1 -1
  24. package/test/r167-release-contract.test.mjs +10 -10
  25. package/test/r168-release-contract.test.mjs +4 -4
  26. package/test/r172-release-contract.test.mjs +5 -5
  27. package/test/r173-release-contract.test.mjs +15 -15
  28. package/test/r179-release-contract.test.mjs +10 -10
  29. package/test/r190-release-contract.test.mjs +8 -8
  30. package/test/r191-release-contract.test.mjs +10 -10
  31. package/test/r192-release-identity.test.mjs +9 -9
  32. package/test/r193-release-identity.test.mjs +21 -21
  33. package/test/r193-release-readiness.test.mjs +2 -2
  34. package/test/r193-windows-gate.test.mjs +10 -10
  35. package/test/r194-release-identity.test.mjs +10 -10
  36. package/test/r194-release-readiness.test.mjs +3 -3
  37. package/test/r194-windows-gate.test.mjs +8 -8
  38. package/test/r206-release-contract.test.mjs +14 -14
  39. package/test/r207-owner-enrollment-io.test.mjs +37 -0
  40. package/test/r207-release-contract.test.mjs +51 -0
  41. package/test/r207-release-readiness.test.mjs +23 -0
  42. package/test/r59-tool-surface-compat.test.mjs +1 -1
@@ -0,0 +1,104 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param(
4
+ [ValidateSet('preflight','focused','full','manifest','doctor','all')][string]$Stage='preflight'
5
+ )
6
+ Set-StrictMode -Version Latest
7
+ $ErrorActionPreference='Stop'
8
+ $repo=Split-Path -Parent $PSScriptRoot
9
+ $productionState=Join-Path $env:USERPROFILE '.deadbyte-mcp'
10
+ $parentId='v0.15.75-9039fff265696091'
11
+ $parentSha='9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248'
12
+ $parentGen='83a212e01173c73f78cff2a6d26e6f3f50f476a8c0ea3cbbf592a466071909e9'
13
+ $parentTarball='c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9'
14
+ $nativeNode='C:\Program Files\nodejs\node.exe'
15
+ $node=if(Test-Path -LiteralPath $nativeNode -PathType Leaf){$nativeNode}else{(Get-Command node -ErrorAction Stop).Source}
16
+ function Sha([string]$file){
17
+ $sha=[Security.Cryptography.SHA256]::Create()
18
+ try{$stream=[IO.File]::OpenRead($file);try{return ([BitConverter]::ToString($sha.ComputeHash($stream))).Replace('-','').ToLowerInvariant()}finally{$stream.Dispose()}}finally{$sha.Dispose()}
19
+ }
20
+ function Need([bool]$condition,[string]$message){if(-not $condition){throw $message}}
21
+ function Run-Node([string]$label,[string[]]$nodeArgs){
22
+ Need ($null -ne $nodeArgs -and $nodeArgs.Count -gt 0) "R207_${label}_NO_NODE_ARGUMENTS"
23
+ Write-Output "R207_STAGE_START=$label"
24
+ $global:LASTEXITCODE=0
25
+ & $node @nodeArgs
26
+ $exit=$global:LASTEXITCODE
27
+ if($exit -ne 0){throw "R207_${label}_FAILED exit=$exit"}
28
+ Write-Output "R207_STAGE_PASS=$label"
29
+ }
30
+ Push-Location $repo
31
+ $previousExpectedDevelopmentRoot=$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT
32
+ try{
33
+ $pkg=Get-Content -LiteralPath 'package.json' -Raw | ConvertFrom-Json
34
+ $release=Get-Content -LiteralPath 'RELEASE.json' -Raw | ConvertFrom-Json
35
+ Need (-not [string]::IsNullOrWhiteSpace([string]$release.r207.development_policy_root)) 'R207_DEVELOPMENT_PROVENANCE_ROOT_MISSING'
36
+ $env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=[IO.Path]::GetFullPath([string]$release.r207.development_policy_root)
37
+ Need ($pkg.version -eq '0.15.76' -and $release.version -eq '0.15.76' -and $release.train -eq 'R207') 'R207_CANDIDATE_VERSION_DRIFT'
38
+ Need ($release.source_predecessor.version -eq '0.15.75' -and $release.source_predecessor.train -eq 'R206') 'R207_SOURCE_PREDECESSOR_VERSION_DRIFT'
39
+ Need ($release.source_predecessor.manifest_sha256 -eq $parentSha -and $release.source_predecessor.tarball_sha256 -eq $parentTarball) 'R207_SOURCE_PREDECESSOR_IDENTITY_DRIFT'
40
+ Need ($release.runtime_predecessor.release_id -eq $parentId -and $release.runtime_predecessor.manifest_sha256 -eq $parentSha -and $release.runtime_predecessor.generation_manifest_sha256 -eq $parentGen) 'R207_RUNTIME_PREDECESSOR_IDENTITY_DRIFT'
41
+ $active=Get-Content -LiteralPath (Join-Path $productionState 'active-release.json') -Raw | ConvertFrom-Json
42
+ Need ($active.version -eq '0.15.75' -and $active.release_id -eq $parentId -and $active.manifest_sha256 -eq $parentSha -and $active.generation_manifest_sha256 -eq $parentGen) 'R207_ACTIVE_RUNTIME_DRIFT'
43
+ Need ((Sha (Join-Path $active.release_root 'MANIFEST.SHA256')) -eq $parentSha) 'R207_ACTIVE_MANIFEST_MISMATCH'
44
+ Write-Output 'R207_PREDECESSOR_PREFLIGHT=PASS'
45
+ if($Stage -eq 'preflight'){return}
46
+ if($Stage -in @('focused','all')){
47
+ $focused=@(
48
+ 'test/r70-owner-approval.test.mjs',
49
+ 'test/r89-privileged-install-boundary.test.mjs',
50
+ 'test/r186-controller-owner-grant.test.mjs',
51
+ 'test/r186-owner-consent-preflight.test.mjs',
52
+ 'test/r186-owner-enrollment.test.mjs',
53
+ 'test/r186-owner-grant-broker.test.mjs',
54
+ 'test/r186-owner-local-signing.test.mjs',
55
+ 'test/r186-owner-request.test.mjs',
56
+ 'test/r186-owner-review-export.test.mjs',
57
+ 'test/r188-owner-uac.test.mjs',
58
+ 'test/r188-uac-boundary.test.mjs',
59
+ 'test/r193-live-owner-subject.test.mjs',
60
+ 'test/r193-owner-enrollment-entrypoint.test.mjs',
61
+ 'test/r193-owner-secret-acl.test.mjs',
62
+ 'test/r193-owner-uac-broker.test.mjs',
63
+ 'test/r193-owner-uac-entrypoint.test.mjs',
64
+ 'test/r195-canonical-owner-observation.test.mjs',
65
+ 'test/r207-owner-enrollment-io.test.mjs',
66
+ 'test/r207-release-contract.test.mjs'
67
+ )
68
+ Run-Node -label 'focused' -nodeArgs (@('--test','--test-reporter=tap','--test-concurrency=1')+$focused)
69
+ if($Stage -eq 'focused'){return}
70
+ }
71
+ if($Stage -in @('full','all')){
72
+ $previousCrossVolume=$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT
73
+ $tempDrive=[IO.Path]::GetPathRoot([IO.Path]::GetFullPath($env:TEMP))
74
+ $scratchDrive=if($tempDrive -ieq 'D:\'){'C:\'}else{'D:\'}
75
+ Need (Test-Path -LiteralPath $scratchDrive -PathType Container) 'R207_CROSS_VOLUME_DRIVE_UNAVAILABLE'
76
+ $crossVolume=Join-Path $scratchDrive 'DEADBYTE-R207-CrossVolume'
77
+ try{
78
+ [IO.Directory]::CreateDirectory($crossVolume)|Out-Null
79
+ $env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$crossVolume
80
+ Run-Node -label 'full' -nodeArgs @('--test','--test-reporter=tap','--test-concurrency=4','test/*.test.mjs')
81
+ }finally{$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$previousCrossVolume}
82
+ if($Stage -eq 'full'){return}
83
+ }
84
+ if($Stage -in @('manifest','all')){
85
+ Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
86
+ if($Stage -eq 'manifest'){return}
87
+ }
88
+ if($Stage -in @('doctor','all')){
89
+ $previousStateRoot=$env:DEADBYTE_STATE_ROOT
90
+ $isolated=Join-Path $env:TEMP ('deadbyte-r207-doctor-'+[guid]::NewGuid().ToString('N'))
91
+ try{
92
+ [IO.Directory]::CreateDirectory($isolated)|Out-Null
93
+ $env:DEADBYTE_STATE_ROOT=$isolated
94
+ Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
95
+ }finally{
96
+ $env:DEADBYTE_STATE_ROOT=$previousStateRoot
97
+ Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
98
+ }
99
+ }
100
+ Write-Output 'R207_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
101
+ }finally{
102
+ $env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=$previousExpectedDevelopmentRoot
103
+ Pop-Location
104
+ }
@@ -17,6 +17,7 @@ import {assertR193NpmPublishReady,assertR193PackedIdentity} from './npm-release-
17
17
  import {assertR194NpmPublishReady,assertR194PackedIdentity} from './npm-release-readiness-r194.mjs';
18
18
  import {assertR195NpmPublishReady,assertR195PackedIdentity} from './npm-release-readiness-r195.mjs';
19
19
  import {assertR206NpmPublishReady,assertR206PackedIdentity} from './npm-release-readiness-r206.mjs';
20
+ import {assertR207NpmPublishReady,assertR207PackedIdentity} from './npm-release-readiness-r207.mjs';
20
21
  import {resumePackRecord} from '../src/npm-publication-resume-r168.mjs';
21
22
  import { existsSync,mkdtempSync,readdirSync,readFileSync,rmSync } from 'node:fs';
22
23
  import { resolveStateRoot } from '../src/state-root.mjs';
@@ -166,6 +167,11 @@ async function main() {
166
167
  if(release.train==='R206')r206Readiness=await assertR206NpmPublishReady(release,{root});
167
168
  else r195Readiness=await assertR195NpmPublishReady(release,{root});
168
169
  }
170
+ let r207Readiness=null;
171
+ if (!isVerifyOnly && version==='0.15.76') {
172
+ if (!publishOnly) throw new Error('PUBLISH_BLOCKED R207 requires --publish-only; owner enrollment and activation remain separate');
173
+ r207Readiness=await assertR207NpmPublishReady(release,{root});
174
+ }
169
175
  if (release.parent?.release_id !== provenance.parent_release_id ||
170
176
  release.parent?.manifest_sha256 !== provenance.parent_manifest_sha256 ||
171
177
  release.parent?.generation_manifest_sha256 !== provenance.parent_generation_manifest_sha256) {
@@ -322,6 +328,10 @@ async function main() {
322
328
  observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
323
329
  });
324
330
 
331
+ if(r207Readiness)assertR207PackedIdentity({
332
+ ...r207Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
333
+ observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
334
+ });
325
335
  console.log('[6/7] Publishing artifact to npm registry...');
326
336
  publishAttempted = true;
327
337
  const ownerAuth=async subject=>
@@ -0,0 +1,76 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {lstat,readFile} from 'node:fs/promises';
3
+ import path from 'node:path';
4
+
5
+ const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
6
+ const hex64=value=>typeof value==='string'&&/^[0-9a-f]{64}$/.test(value);
7
+ const fail=message=>{throw new Error(`PUBLISH_BLOCKED R207 ${message}`);};
8
+ const required=(value,message)=>{if(!value)fail(message);};
9
+
10
+ async function checkedFile(file,expected,{maxBytes=64*1024*1024}={}){
11
+ required(hex64(expected),'evidence digest missing');
12
+ let info;try{info=await lstat(file);}catch{fail('evidence file absent');}
13
+ required(info.isFile()&&!info.isSymbolicLink()&&info.size>0&&info.size<=maxBytes,'evidence file invalid');
14
+ const bytes=await readFile(file);
15
+ required(sha256(bytes)===expected,'evidence digest differs');
16
+ return bytes;
17
+ }
18
+
19
+ function tapSummary(text,label){
20
+ const summaries=[...text.matchAll(/^# tests (\d+)\s*\r?\n# suites (\d+)\s*\r?\n# pass (\d+)\s*\r?\n# fail (\d+)\s*\r?\n# cancelled (\d+)\s*\r?\n# skipped (\d+)/gm)];
21
+ required(summaries.length>0,`${label} TAP summary absent`);
22
+ const last=summaries.at(-1);
23
+ return {tests:Number(last[1]),passes:Number(last[3]),fails:Number(last[4]),cancelled:Number(last[5]),skips:Number(last[6])};
24
+ }
25
+
26
+ export function assertR207PackedIdentity({tarball_sha256,tarball_integrity,tarball_shasum,observedSha256,observedIntegrity,observedShasum}={}){
27
+ required(hex64(tarball_sha256)&&typeof tarball_integrity==='string'&&tarball_integrity.startsWith('sha512-')&&
28
+ typeof tarball_shasum==='string'&&/^[0-9a-f]{40}$/.test(tarball_shasum),'verified tarball identity invalid');
29
+ required(observedSha256===tarball_sha256&&observedIntegrity===tarball_integrity&&observedShasum===tarball_shasum,
30
+ 'repacked tarball differs from verified closure bytes');
31
+ return true;
32
+ }
33
+
34
+ export async function assertR207NpmPublishReady(release,{root,closureRoot=process.env.DEADBYTE_R207_CLOSURE_ROOT}={}){
35
+ required(release?.version==='0.15.76'&&release?.train==='R207'&&
36
+ release?.r207?.scope==='PROTECTED_OWNER_ENROLLMENT_IO_RECOVERY','candidate metadata invalid');
37
+ required(release?.r207?.public_tool_delta===0&&release?.r207?.authority_scope_delta===0&&
38
+ release?.r207?.owner_private_key_access===false&&release?.r207?.r70_weakened===false&&release?.r207?.r89_weakened===false,'public authority surface widened');
39
+ required(release?.source_predecessor?.train==='R206'&&
40
+ release?.source_predecessor?.manifest_sha256==='9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248',
41
+ 'source predecessor mismatch');
42
+ required(release?.parent?.version==='0.15.75'&&release?.parent?.release_id==='v0.15.75-9039fff265696091'&&
43
+ release?.parent?.manifest_sha256==='9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248'&&
44
+ release?.parent?.generation_manifest_sha256==='83a212e01173c73f78cff2a6d26e6f3f50f476a8c0ea3cbbf592a466071909e9','lineage mismatch');
45
+ required(root&&path.isAbsolute(root)&&closureRoot&&path.isAbsolute(closureRoot),'closure root absent');
46
+ const expected=path.resolve(root,'..','..','testing','r207-final-closure');
47
+ required(path.resolve(closureRoot).toLowerCase()===expected.toLowerCase(),'closure root outside scoped testing folder');
48
+ let closure;try{closure=JSON.parse(await readFile(path.join(closureRoot,'closure.json'),'utf8'));}catch{fail('closure unreadable');}
49
+ required(closure?.schema==='deadbyte.r207-release-closure.v1'&&closure.status==='RELEASE_READY'&&
50
+ closure.version==='0.15.76'&&closure.train==='R207','closure status mismatch');
51
+ required(closure.production_release_id===release.parent.release_id&&closure.production_manifest_sha256===release.parent.manifest_sha256&&
52
+ closure.production_generation_manifest_sha256===release.parent.generation_manifest_sha256,'production predecessor mismatch');
53
+ required(hex64(closure.manifest_sha256)&&closure.manifest_sha256===sha256(await readFile(path.join(root,'MANIFEST.SHA256'))),'final manifest drift');
54
+ required(closure.compact_tools===43&&closure.full_tools===117,'catalog count mismatch');
55
+ required(closure.owner_enrollment==='NOT_RUN'&&closure.production_activation==='NOT_RUN','prepublication closure crossed authority boundary');
56
+ const receipt=JSON.parse((await checkedFile(path.join(closureRoot,'protected-install-receipt.json'),closure.protected_receipt_sha256)).toString('utf8'));
57
+ required(receipt?.status==='PASS'&&receipt.package_version==='0.15.76'&&receipt.source_manifest_sha256===closure.manifest_sha256&&
58
+ receipt.protected_manifest_sha256===closure.manifest_sha256,'protected exact-byte receipt mismatch');
59
+ const focused=(await checkedFile(path.join(closureRoot,'windows-focused.stdout.log'),closure.focused_stdout_sha256)).toString('utf8');
60
+ const full=(await checkedFile(path.join(closureRoot,'windows-full.stdout.log'),closure.full_stdout_sha256)).toString('utf8');
61
+ const verify=(await checkedFile(path.join(closureRoot,'npm-verify.stdout.log'),closure.verify_stdout_sha256)).toString('utf8');
62
+ required(focused.includes('R207_STAGE_PASS=focused'),'focused protected gate incomplete');
63
+ const focusedSummary=tapSummary(focused,'focused');
64
+ required(focusedSummary.tests>=55&&focusedSummary.fails===0&&focusedSummary.cancelled===0&&focusedSummary.passes>=54&&focusedSummary.skips<=1&&focusedSummary.passes+focusedSummary.skips===focusedSummary.tests,'focused regression count mismatch');
65
+ required(full.includes('R207_STAGE_PASS=full'),'full protected gate incomplete');
66
+ const summary=tapSummary(full,'full');
67
+ required(summary.tests>=2200&&summary.passes>=2100&&summary.fails===0&&summary.cancelled===0&&summary.skips<=70&&summary.passes+summary.skips===summary.tests,'full regression count mismatch');
68
+ required(verify.includes('VERIFY-ONLY PIPELINE PASS')&&verify.includes('Artifact isolation gate PASS')&&verify.includes('VERIFIED_TARBALL '),'npm exact-artifact verification incomplete');
69
+ const line=verify.split(/\r?\n/).find(value=>value.startsWith('VERIFIED_TARBALL '));
70
+ let artifact;try{artifact=JSON.parse(line.slice('VERIFIED_TARBALL '.length));}catch{fail('tarball evidence malformed');}
71
+ required(artifact.filename==='deadbyte-mcp-0.15.76.tgz'&&artifact.bytes>0&&artifact.sha256===closure.tarball_sha256&&
72
+ artifact.integrity===closure.tarball_integrity&&artifact.shasum===closure.tarball_shasum,'tarball identity mismatch');
73
+ return Object.freeze({status:'R207_RELEASE_READY_EVIDENCE_BOUND',manifest_sha256:closure.manifest_sha256,
74
+ tarball_sha256:artifact.sha256,tarball_integrity:artifact.integrity,tarball_shasum:artifact.shasum,
75
+ tests:summary.tests,passes:summary.passes,skips:summary.skips});
76
+ }
@@ -9,6 +9,7 @@ import {parseManifest,verifyManifestTreeExact} from '../src/release-slot.mjs';
9
9
  import {createR188OwnerUacRequest} from '../src/r188-owner-uac.mjs';
10
10
  import {createR193LiveMachineEpoch} from '../src/r193-live-owner-subject.mjs';
11
11
  import {observeCanonicalController} from '../src/r195-canonical-owner-observation.mjs';
12
+ import {ensureOwnerConsentDirectory} from '../src/r207-owner-enrollment-io.mjs';
12
13
  import {execFile} from 'node:child_process';
13
14
  import {promisify} from 'node:util';
14
15
  const execFileAsync=promisify(execFile);
@@ -40,7 +41,8 @@ async function main(){
40
41
  const request=createR188OwnerUacRequest({machineEpoch,releaseManifestSha256:sha(manifestBytes),
41
42
  codingPolicySha256:sha(codingBytes),autonomousPolicySha256:sha(autonomousBytes),
42
43
  rootId:'core',projectRoot:coding.roots.core.path,maxSeconds:600,now:new Date(),expiresInMs:300000});
43
- const out=path.win32.join(RUNTIME,'owner-consent','r193-request-'+request.request_sha256+'.json');
44
+ const consentDir=await ensureOwnerConsentDirectory(RUNTIME);
45
+ const out=path.win32.join(consentDir,'r193-request-'+request.request_sha256+'.json');
44
46
  const handle=await open(out,'wx',0o600);try{await handle.writeFile(canonicalJson(request)+'\n');await handle.sync();}finally{await handle.close();}
45
47
  process.stdout.write(JSON.stringify({status:'R193_OWNER_REQUEST_CREATED',request_path:out,
46
48
  request_sha256:request.request_sha256,review_phrase:request.review_phrase,
@@ -16,6 +16,7 @@ import {approveR193OwnerRequest} from '../src/r193-owner-uac-broker.mjs';
16
16
  import {createR186OwnerAnchor} from '../src/r186-owner-anchor.mjs';
17
17
  import {inspectR193OwnerSecretAcl} from '../src/r193-owner-secret-acl.mjs';
18
18
  import {observeCanonicalController} from '../src/r195-canonical-owner-observation.mjs';
19
+ import {parseOwnerEnrollmentJson} from '../src/r207-owner-enrollment-io.mjs';
19
20
 
20
21
  const execFileAsync=promisify(execFile);
21
22
  const THIS=fileURLToPath(import.meta.url),ROOT=path.resolve(path.dirname(THIS),'..');
@@ -82,7 +83,7 @@ async function live(request){
82
83
  const env={...process.env,DEADBYTE_CONTROLLER_CONFIG:configPath,
83
84
  DEADBYTE_CONTROLLER_RUNTIME_ROOT:RUNTIME};
84
85
  const observation=await observeCanonicalController({stateRoot:STATE,powershell:PS,env,execFileAsync});
85
- const supervisor=JSON.parse((await bounded(path.win32.join(RUNTIME,'supervisor.instance.json'),64*1024)).toString('utf8'));
86
+ const supervisor=parseOwnerEnrollmentJson(await bounded(path.win32.join(RUNTIME,'supervisor.instance.json'),64*1024),'supervisor ledger');
86
87
  const sources={bridge:observation.bridge,core:observation.core,cloud:observation.cloud,supervisor};
87
88
  const processReports={};
88
89
  for(const component of ['bridge','core','cloud','supervisor'])
@@ -101,7 +102,7 @@ async function main(){
101
102
  if(!['preflight','approve'].includes(mode)||process.argv.slice(2).length!==2||
102
103
  !path.win32.isAbsolute(requestPath))block('usage: <preflight|approve> <absolute-request-json>');
103
104
  await inspectTrustedInstallation([NODE,THIS,path.join(ROOT,'MANIFEST.SHA256'),NATIVE]);
104
- const request=JSON.parse((await bounded(requestPath,64*1024)).toString('utf8'));
105
+ const request=parseOwnerEnrollmentJson(await bounded(requestPath,64*1024),'owner request');
105
106
  const state=await live(request);
106
107
  if(mode==='preflight'){
107
108
  process.stdout.write(JSON.stringify({status:'READY_FOR_OWNER_GESTURE',
@@ -0,0 +1,30 @@
1
+ import {lstat,mkdir,realpath} from 'node:fs/promises';
2
+ import path from 'node:path';
3
+
4
+ export function parseOwnerEnrollmentJson(bytes,label='owner enrollment JSON'){
5
+ const text=Buffer.isBuffer(bytes)?bytes.toString('utf8'):String(bytes);
6
+ let value;
7
+ try{value=JSON.parse(text.replace(/^\uFEFF/,''));}
8
+ catch(error){throw new Error(`${label} is invalid JSON: ${String(error?.message??error)}`);}
9
+ if(!value||typeof value!=='object'||Array.isArray(value))throw new Error(`${label} must be an object`);
10
+ return value;
11
+ }
12
+
13
+ export async function ensureOwnerConsentDirectory(runtimeDir){
14
+ if(typeof runtimeDir!=='string'||!path.win32.isAbsolute(runtimeDir))
15
+ throw new Error('owner consent runtime root must be an absolute Windows path');
16
+ const runtime=path.win32.resolve(runtimeDir);
17
+ const runtimeInfo=await lstat(runtime);
18
+ if(!runtimeInfo.isDirectory()||runtimeInfo.isSymbolicLink())
19
+ throw new Error('owner consent runtime root must be a real directory');
20
+ const runtimeReal=path.win32.resolve(await realpath(runtime));
21
+ const consent=path.win32.join(runtime,'owner-consent');
22
+ await mkdir(consent,{recursive:true});
23
+ const consentInfo=await lstat(consent);
24
+ if(!consentInfo.isDirectory()||consentInfo.isSymbolicLink())
25
+ throw new Error('owner consent path must be a real directory');
26
+ const consentReal=path.win32.resolve(await realpath(consent));
27
+ if(path.win32.dirname(consentReal).toLowerCase()!==runtimeReal.toLowerCase())
28
+ throw new Error('owner consent path escapes the runtime root');
29
+ return consentReal;
30
+ }
package/src/version.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export const DEADBYTE_VERSION = '0.15.75';
1
+ export const DEADBYTE_VERSION = '0.15.76';
2
2
  export const MCP_PROTOCOL_VERSION = '2026-07-28';
3
3
  export const RECEIPT_SCHEMA_V1 = 'deadbyte.receipt.v1';
4
4
  export const RECEIPT_SCHEMA_V2 = 'deadbyte.receipt.v2';
@@ -70,13 +70,13 @@ test('R167 process policy binds coherently to the explicit development root', as
70
70
  // The distributed policy is pinned to its explicit development provenance,
71
71
  // not to the physical extraction path of the exact immutable npm tarball.
72
72
  const release = JSON.parse(await readFile(path.join(repoRoot, 'RELEASE.json'), 'utf8'));
73
- const approvedRoot = release.r206?.development_policy_root;
74
- assert.equal(typeof approvedRoot, 'string', 'R206 development policy root must be explicit in release metadata');
75
- assert.ok(path.isAbsolute(approvedRoot), 'R206 development policy root must be absolute');
73
+ const approvedRoot = release.r207?.development_policy_root;
74
+ assert.equal(typeof approvedRoot, 'string', 'R207 development policy root must be explicit in release metadata');
75
+ assert.ok(path.isAbsolute(approvedRoot), 'R207 development policy root must be absolute');
76
76
  const expectedRoot = path.resolve(approvedRoot);
77
77
  if (process.env.DEADBYTE_EXPECTED_DEVELOPMENT_ROOT) {
78
78
  assert.equal(path.resolve(process.env.DEADBYTE_EXPECTED_DEVELOPMENT_ROOT), expectedRoot,
79
- 'caller-supplied development root cannot override R206 release provenance');
79
+ 'caller-supplied development root cannot override R207 release provenance');
80
80
  }
81
81
  const policyPath = path.join(repoRoot, 'controller', 'deadbyte-process-policy.json');
82
82
  const policy = JSON.parse(await readFile(policyPath, 'utf8'));
@@ -14,14 +14,14 @@ test('current successor retains the R130 security baseline with truthful R190 id
14
14
  read('SBOM.cdx.json'),readReleaseLock(root),read('TEST-MATRIX.json')]);
15
15
  assert.equal(pkg.name,'deadbyte-mcp');
16
16
  for(const actual of [pkg.version,release.version,provenance.version,matrix.version,bom.metadata.component.version,lock.version,lock.packages[''].version,DEADBYTE_VERSION])
17
- assert.equal(actual,'0.15.75');
18
- assert.equal(release.train,'R206');
19
- assert.equal(matrix.train,'R206');
17
+ assert.equal(actual,'0.15.76');
18
+ assert.equal(release.train,'R207');
19
+ assert.equal(matrix.train,'R207');
20
20
  assert.equal(release.source_predecessor.version,'0.15.75');
21
- assert.equal(release.source_predecessor.train,'R205');
22
- assert.match(release.source_predecessor.source_path,/r205-evidence-selection-dev/i);
23
- assert.equal(release.source_predecessor.manifest_status,'R205_MANIFEST_VERIFIED');
24
- assert.equal(release.runtime_predecessor.version,'0.15.74');
21
+ assert.equal(release.source_predecessor.train,'R206');
22
+ assert.match(release.source_predecessor.source_path,/r206-release-closure/i);
23
+ assert.equal(release.source_predecessor.manifest_status,'R206_MANIFEST_VERIFIED');
24
+ assert.equal(release.runtime_predecessor.version,'0.15.75');
25
25
  assert.equal(provenance.r160.source_predecessor_manifest_status,'STALE_REJECTED');
26
26
  assert.equal(pkg.dependencies['@modelcontextprotocol/client'],'2.3.1');
27
27
  assert.equal(pkg.dependencies['@modelcontextprotocol/server'],'2.3.1');
@@ -16,17 +16,17 @@ test('R190 package identity preserves R132 evidence and published R179 source pr
16
16
  for(const value of [pkg.version,lock.version,lock.packages[''].version,release.version,prov.version,bom.metadata.component.version,matrix.version,DEADBYTE_VERSION]){
17
17
  assert.equal(value,pkg.version);
18
18
  }
19
- assert.equal(release.train,'R206');
20
- assert.equal(matrix.train,'R206');
19
+ assert.equal(release.train,'R207');
20
+ assert.equal(matrix.train,'R207');
21
21
  assert.equal(release.source_predecessor.version,'0.15.75');
22
- assert.equal(release.source_predecessor.train,'R205');
23
- assert.match(release.source_predecessor.source_path,/r205-evidence-selection-dev/i);
22
+ assert.equal(release.source_predecessor.train,'R206');
23
+ assert.match(release.source_predecessor.source_path,/r206-release-closure/i);
24
24
  assert.equal(prov.r160.source_predecessor_manifest_status,'STALE_REJECTED');
25
25
  assert.equal(release.r165.published_source_manifest_sha256,'4adf7d94682fbb71c4a91eb3147ecc48076bbc5d79cb67fcb875cde6a1bb4805');
26
26
  assert.equal(release.r165.published_source_tarball_sha256,'812e97609b7c51353ed25f2202129737e43bb4fbe0778c3adec43ec065352641');
27
- assert.equal(release.source_predecessor.tarball_sha256,null);
27
+ assert.equal(release.source_predecessor.tarball_sha256,'c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9');
28
28
  assert.notEqual(release.r179.source_predecessor_tarball_sha256,release.source_predecessor.tarball_sha256);
29
- assert.equal(release.runtime_predecessor.version,'0.15.74');
29
+ assert.equal(release.runtime_predecessor.version,'0.15.75');
30
30
  assert.equal(prov.runtime_predecessor.release_id,release.runtime_predecessor.release_id);
31
31
  assert.equal(prov.runtime_predecessor.manifest_sha256,release.runtime_predecessor.manifest_sha256);
32
32
  assert.equal(prov.runtime_predecessor.generation_manifest_sha256,release.runtime_predecessor.generation_manifest_sha256);
@@ -26,7 +26,7 @@ test('R153 historical verifier refuses current successor package identity',async
26
26
  const state={pkg:JSON.parse(await readFile(path.join(root,'package.json'),'utf8')),
27
27
  release:JSON.parse(await readFile(path.join(root,'RELEASE.json'),'utf8')),
28
28
  bridge:JSON.parse(await readFile(path.join(root,'bridge/package.json'),'utf8'))};
29
- assert.equal(state.pkg.version,'0.15.75');
29
+ assert.equal(state.pkg.version,'0.15.76');
30
30
  assert.throws(()=>verifyR153Lineage(state),/package version/);
31
31
  await assert.rejects(verifyR153IdentityTree(root),/package version/);
32
32
  });
@@ -8,9 +8,9 @@ const read=async rel=>JSON.parse(await readFile(path.join(root,rel),'utf8'));
8
8
 
9
9
  test('R160 historical contract remains distinct from the current package identity',async()=>{
10
10
  const [release,provenance]=await Promise.all([read('RELEASE.json'),read('PROVENANCE.json')]);
11
- assert.equal(release.runtime_predecessor.version,'0.15.74');
12
- assert.equal(release.runtime_predecessor.release_id,'v0.15.74-e84bf4eed16e9443');
13
- assert.equal(release.runtime_predecessor.manifest_sha256,'e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47');
11
+ assert.equal(release.runtime_predecessor.version,'0.15.75');
12
+ assert.equal(release.runtime_predecessor.release_id,'v0.15.75-9039fff265696091');
13
+ assert.equal(release.runtime_predecessor.manifest_sha256,'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248');
14
14
  assert.equal(release.r160.runtime_predecessor_version,'0.15.61');
15
15
  assert.equal(release.r160.source_predecessor_train,'R159');
16
16
  assert.equal(release.r160.public_tool_delta,0);
@@ -17,7 +17,7 @@ const hashMarker=c=>c.repeat(64);
17
17
  async function fixture(t,kind){
18
18
  assert.equal(typeof envRoot,'string'); assert.ok(path.isAbsolute(envRoot));
19
19
  assert.match(sha(await readFile(path.join(envRoot,'MANIFEST.SHA256'))),/^[0-9a-f]{64}$/);
20
- assert.equal(JSON.parse(await readFile(path.join(envRoot,'package.json'),'utf8')).version,'0.15.75');
20
+ assert.equal(JSON.parse(await readFile(path.join(envRoot,'package.json'),'utf8')).version,'0.15.76');
21
21
  const dir=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r164-skew-e2e-'));
22
22
  t.after(async()=>{await rm(dir,{recursive:true,force:true,maxRetries:10,retryDelay:150});});
23
23
  const state=path.join(dir,'state'),bin=path.join(state,'bin');
@@ -8,7 +8,7 @@ import {DEADBYTE_VERSION} from '../src/version.mjs';
8
8
  const root=path.resolve(fileURLToPath(new URL('..',import.meta.url)));
9
9
  const read=async rel=>JSON.parse(await readFile(path.join(root,rel),'utf8'));
10
10
  const readOptional=async rel=>{try{return await read(rel);}catch(error){if(error?.code==='ENOENT')return null;throw error;}};
11
- const VERSION='0.15.75';
11
+ const VERSION='0.15.76';
12
12
  const R166_MANIFEST='ad3c091fbbe2bac6d234548724008b67305fd483ad6542f92d5aeb1aa84f5849';
13
13
  const R166_TARBALL='3d22412c3cebabd66bfa92ca4dbaaf3ef49acba7f92436a16485d7e4cb18c653';
14
14
 
@@ -20,20 +20,20 @@ test('current package identity retains the immutable R167/R173 activation lineag
20
20
  provenance.version,matrix.version,bom.metadata.component.version,DEADBYTE_VERSION];
21
21
  if(lock)versions.push(lock.version,lock.packages[''].version);
22
22
  for(const version of versions)assert.equal(version,VERSION);
23
- assert.equal(release.train,'R206');
24
- assert.equal(matrix.train,'R206');
25
- assert.equal(bom.serialNumber,'urn:cdx:deadbyte-mcp:r206:0.15.75');
23
+ assert.equal(release.train,'R207');
24
+ assert.equal(matrix.train,'R207');
25
+ assert.equal(bom.serialNumber,'urn:cdx:deadbyte-mcp:r207:0.15.76');
26
26
  assert.deepEqual(release.runtime_predecessor,{
27
- version:'0.15.74',release_id:'v0.15.74-e84bf4eed16e9443',
28
- manifest_sha256:'e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47',
29
- generation_manifest_sha256:'598f896be9ce65e6b0c618e8c8f6eaa2a9d91617a76a146bf3deb385a56d19e7'
27
+ version:'0.15.75',release_id:'v0.15.75-9039fff265696091',
28
+ manifest_sha256:'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248',
29
+ generation_manifest_sha256:'83a212e01173c73f78cff2a6d26e6f3f50f476a8c0ea3cbbf592a466071909e9'
30
30
  });
31
31
  assert.equal(release.source_predecessor.version,'0.15.75');
32
- assert.equal(release.source_predecessor.train,'R205');
33
- assert.equal(release.source_predecessor.tarball_sha256,null);
32
+ assert.equal(release.source_predecessor.train,'R206');
33
+ assert.equal(release.source_predecessor.tarball_sha256,'c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9');
34
34
  assert.equal(release.r173.source_predecessor_version,'0.15.67');
35
35
  assert.equal(release.r167.source_predecessor_manifest_sha256,R166_MANIFEST);
36
- assert.equal(provenance.source_predecessor_manifest_file_sha256,'166eebde18d53a9ec46f738383c289733f9cd37918b3572b7515d1ab9b122c92');
36
+ assert.equal(provenance.source_predecessor_manifest_file_sha256,'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248');
37
37
  assert.equal(provenance.r173.source_predecessor_manifest_sha256,'4fd7bfc76b1de6401c142b607cc84e847434b28c888bc99ceb09c9e8e5adc8f8');
38
38
  assert.equal(release.r172.source_predecessor_manifest_sha256,'962e227dace247d59aa860211388fbde461c5f9c8a7e8a878e34a14a27d355f8');
39
39
  assert.equal(release.r172.source_predecessor_tarball_sha256,'31b194a4fbff7dbdb9f4f275b4ea49c5115f7b0bb2241c0c72d72ef690311a5d');
@@ -13,10 +13,10 @@ const predecessorTarball='fc3ae5b1505e316bc9dfedf8d063cb00641754c8f5f1306a31f8cc
13
13
 
14
14
  test('R172 preserves the immutable R168 publication lineage separately from current identity',async()=>{
15
15
  const release=await read('RELEASE.json');
16
- assert.equal(release.runtime_predecessor.version,'0.15.74');
17
- assert.equal(release.parent.version,'0.15.74');
18
- assert.equal(release.runtime_predecessor.release_id,'v0.15.74-e84bf4eed16e9443');
19
- assert.equal(release.parent.release_id,'v0.15.74-e84bf4eed16e9443');
16
+ assert.equal(release.runtime_predecessor.version,'0.15.75');
17
+ assert.equal(release.parent.version,'0.15.75');
18
+ assert.equal(release.runtime_predecessor.release_id,'v0.15.75-9039fff265696091');
19
+ assert.equal(release.parent.release_id,'v0.15.75-9039fff265696091');
20
20
  assert.notEqual(release.runtime_predecessor.release_id,parent);
21
21
  assert.notEqual(release.parent.release_id,parent);
22
22
  assert.equal(release.r168.scope,'REMOTE_VERSION_SKEW_FAIL_CLOSED_AND_READONLY_RECONCILIATION');
@@ -16,12 +16,12 @@ test('R190 binds the published source predecessor separately from the active run
16
16
  const versions=[pkg.version,bridge.version,release.version,provenance.version,matrix.version,
17
17
  bom.metadata.component.version,DEADBYTE_VERSION];
18
18
  if(lock)versions.push(lock.version,lock.packages[''].version);
19
- for(const value of versions)assert.equal(value,'0.15.75');
20
- assert.equal(release.train,'R206'); assert.equal(matrix.train,'R206');
19
+ for(const value of versions)assert.equal(value,'0.15.76');
20
+ assert.equal(release.train,'R207'); assert.equal(matrix.train,'R207');
21
21
  assert.equal(release.source_predecessor.version,'0.15.75');
22
- assert.equal(release.source_predecessor.manifest_sha256,'166eebde18d53a9ec46f738383c289733f9cd37918b3572b7515d1ab9b122c92');
23
- assert.equal(release.source_predecessor.tarball_sha256,null);
24
- assert.equal(release.runtime_predecessor.release_id,'v0.15.74-e84bf4eed16e9443');
22
+ assert.equal(release.source_predecessor.manifest_sha256,'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248');
23
+ assert.equal(release.source_predecessor.tarball_sha256,'c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9');
24
+ assert.equal(release.runtime_predecessor.release_id,'v0.15.75-9039fff265696091');
25
25
  assert.equal(release.r173.public_tool_delta,0); assert.equal(release.r173.authority_scope_delta,0);
26
26
  });
27
27
 
@@ -13,21 +13,21 @@ test('R190 package identity binds the exact published R179 source and live runti
13
13
  json('package.json'),readReleaseLock(root),json('bridge/package.json'),json('RELEASE.json'),
14
14
  json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json')
15
15
  ]);
16
- assert.equal(pkg.version,'0.15.75');
17
- assert.equal(lock.version,'0.15.75');
18
- assert.equal(lock.packages[''].version,'0.15.75');
19
- assert.equal(bridge.version,'0.15.75');
20
- assert.equal(release.version,'0.15.75');
21
- assert.equal(release.train,'R206');
22
- assert.equal(matrix.version,'0.15.75');
23
- assert.equal(matrix.train,'R206');
24
- assert.equal(sbom.metadata.component.version,'0.15.75');
16
+ assert.equal(pkg.version,'0.15.76');
17
+ assert.equal(lock.version,'0.15.76');
18
+ assert.equal(lock.packages[''].version,'0.15.76');
19
+ assert.equal(bridge.version,'0.15.76');
20
+ assert.equal(release.version,'0.15.76');
21
+ assert.equal(release.train,'R207');
22
+ assert.equal(matrix.version,'0.15.76');
23
+ assert.equal(matrix.train,'R207');
24
+ assert.equal(sbom.metadata.component.version,'0.15.76');
25
25
  assert.equal(release.source_predecessor.version,'0.15.75');
26
- assert.equal(release.source_predecessor.train,'R205');
27
- assert.equal(release.source_predecessor.manifest_sha256,'166eebde18d53a9ec46f738383c289733f9cd37918b3572b7515d1ab9b122c92');
28
- assert.equal(release.source_predecessor.tarball_sha256,null);
29
- assert.equal(release.runtime_predecessor.version,'0.15.74');
30
- assert.equal(provenance.version,'0.15.75');
31
- assert.equal(provenance.parent_tarball_sha256,'5da436a3f8068107e74caf6da58ff1e211d4a62f94266853136b601762f36f0c');
26
+ assert.equal(release.source_predecessor.train,'R206');
27
+ assert.equal(release.source_predecessor.manifest_sha256,'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248');
28
+ assert.equal(release.source_predecessor.tarball_sha256,'c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9');
29
+ assert.equal(release.runtime_predecessor.version,'0.15.75');
30
+ assert.equal(provenance.version,'0.15.76');
31
+ assert.equal(provenance.parent_tarball_sha256,'c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9');
32
32
  assert.equal(provenance.source_predecessor_manifest_file_sha256,release.source_predecessor.manifest_sha256);
33
33
  });
@@ -7,27 +7,27 @@ import {DEADBYTE_VERSION} from '../src/version.mjs';
7
7
  import {readReleaseLock} from './helpers/release-lock.mjs';
8
8
  const root=path.resolve(fileURLToPath(new URL('..',import.meta.url)));
9
9
  const read=async file=>JSON.parse(await readFile(path.join(root,file),'utf8'));
10
- const parent='v0.15.74-e84bf4eed16e9443';
11
- const manifest='e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47';
12
- const generation='598f896be9ce65e6b0c618e8c8f6eaa2a9d91617a76a146bf3deb385a56d19e7';
10
+ const parent='v0.15.75-9039fff265696091';
11
+ const manifest='9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248';
12
+ const generation='83a212e01173c73f78cff2a6d26e6f3f50f476a8c0ea3cbbf592a466071909e9';
13
13
  const tarball='1a7f1fe05a06178b8d772a140be6e0470790b743cef690c3f8f8165cc61075bf';
14
14
  test('R190 version, lock snapshot, bridge, matrix, SBOM and provenance identify exact 0.15.70 successor',async()=>{
15
15
  const [pkg,lock,bridge,release,provenance,matrix,sbom]=await Promise.all([
16
16
  read('package.json'),readReleaseLock(root),read('bridge/package.json'),read('RELEASE.json'),
17
17
  read('PROVENANCE.json'),read('TEST-MATRIX.json'),read('SBOM.cdx.json')]);
18
18
  for(const version of [pkg.version,lock.version,lock.packages[''].version,bridge.version,release.version,provenance.version,
19
- matrix.version,sbom.metadata.component.version,DEADBYTE_VERSION])assert.equal(version,'0.15.75');
20
- assert.equal(release.train,'R206');assert.equal(matrix.train,'R206');
21
- assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r206:0.15.75');
19
+ matrix.version,sbom.metadata.component.version,DEADBYTE_VERSION])assert.equal(version,'0.15.76');
20
+ assert.equal(release.train,'R207');assert.equal(matrix.train,'R207');
21
+ assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r207:0.15.76');
22
22
  assert.equal(release.parent.release_id,parent);assert.equal(release.parent.manifest_sha256,manifest);
23
23
  assert.equal(release.parent.generation_manifest_sha256,generation);
24
24
  assert.equal(release.source_predecessor.version,'0.15.75');
25
- assert.equal(release.source_predecessor.manifest_sha256,'166eebde18d53a9ec46f738383c289733f9cd37918b3572b7515d1ab9b122c92');
26
- assert.equal(release.source_predecessor.tarball_sha256,null);
25
+ assert.equal(release.source_predecessor.manifest_sha256,'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248');
26
+ assert.equal(release.source_predecessor.tarball_sha256,'c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9');
27
27
  assert.equal(release.runtime_predecessor.release_id,parent);
28
28
  assert.equal(provenance.runtime_predecessor.release_id,parent);
29
- assert.equal(provenance.parent_tarball_sha256,'5da436a3f8068107e74caf6da58ff1e211d4a62f94266853136b601762f36f0c');
30
- assert.equal(provenance.source_predecessor_tarball_sha256,null);
29
+ assert.equal(provenance.parent_tarball_sha256,'c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9');
30
+ assert.equal(provenance.source_predecessor_tarball_sha256,'c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9');
31
31
  });
32
32
  test('R179 does not misrepresent owner Autonomous enrollment, protected regression or publication as finished',async()=>{
33
33
  const [release,prov,matrix]=await Promise.all(['RELEASE.json','PROVENANCE.json','TEST-MATRIX.json'].map(read));
@@ -8,17 +8,17 @@ test('R190 candidate identity separates published source 0.15.69 from active run
8
8
  json('package.json'),json('bridge/package.json'),json('RELEASE.json'),json('PROVENANCE.json'),
9
9
  json('TEST-MATRIX.json'),json('SBOM.cdx.json'),readFile(new URL('../src/version.mjs',import.meta.url),'utf8')]);
10
10
  for(const value of [pkg.version,bridge.version,release.version,provenance.version,matrix.version,
11
- sbom.metadata.component.version])assert.equal(value,'0.15.75');
12
- assert.match(versionSource,/DEADBYTE_VERSION = '0\.15\.75'/);
13
- assert.equal(release.train,'R206');assert.equal(matrix.train,'R206');
11
+ sbom.metadata.component.version])assert.equal(value,'0.15.76');
12
+ assert.match(versionSource,/DEADBYTE_VERSION = '0\.15\.76'/);
13
+ assert.equal(release.train,'R207');assert.equal(matrix.train,'R207');
14
14
  assert.equal(release.source_predecessor.version,'0.15.75');
15
- assert.equal(release.source_predecessor.tarball_sha256,null);
16
- assert.equal(release.source_predecessor.manifest_sha256,'166eebde18d53a9ec46f738383c289733f9cd37918b3572b7515d1ab9b122c92');
17
- assert.equal(release.runtime_predecessor.version,'0.15.74');
18
- assert.equal(release.runtime_predecessor.release_id,'v0.15.74-e84bf4eed16e9443');
15
+ assert.equal(release.source_predecessor.tarball_sha256,'c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9');
16
+ assert.equal(release.source_predecessor.manifest_sha256,'9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248');
17
+ assert.equal(release.runtime_predecessor.version,'0.15.75');
18
+ assert.equal(release.runtime_predecessor.release_id,'v0.15.75-9039fff265696091');
19
19
  assert.equal(provenance.source_predecessor_version,'0.15.75');
20
20
  assert.equal(provenance.source_predecessor_tarball_sha256,release.source_predecessor.tarball_sha256);
21
- assert.match(sbom.serialNumber,/r206:0\.15\.75$/);
21
+ assert.match(sbom.serialNumber,/r207:0\.15\.76$/);
22
22
  });
23
23
 
24
24
  test('R190 release metadata records verified recovery without claiming publication or activation',async()=>{