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.
- package/MANIFEST.SHA256 +41 -35
- package/PROVENANCE.json +17 -17
- package/README.txt +12 -12
- package/RELEASE.json +35 -17
- package/SBOM.cdx.json +2 -2
- package/TEST-MATRIX.json +12 -2
- package/bridge/package.json +1 -1
- package/controller/deadbyte-process-policy.json +4 -4
- package/docs/R184-package-lock.json +2 -2
- package/package.json +3 -2
- package/scripts/gate-windows-r207.ps1 +104 -0
- package/scripts/npm-release-r48.mjs +10 -0
- package/scripts/npm-release-readiness-r207.mjs +76 -0
- package/scripts/r193-owner-request-live.mjs +3 -1
- package/scripts/r193-owner-uac-broker.mjs +3 -2
- package/src/r207-owner-enrollment-io.mjs +30 -0
- package/src/version.mjs +1 -1
- package/test/process-policy-refresh.test.mjs +4 -4
- package/test/r130-release-security-contract.test.mjs +7 -7
- package/test/r132-release-identity.test.mjs +6 -6
- 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 +10 -10
- package/test/r168-release-contract.test.mjs +4 -4
- package/test/r172-release-contract.test.mjs +5 -5
- package/test/r173-release-contract.test.mjs +15 -15
- package/test/r179-release-contract.test.mjs +10 -10
- package/test/r190-release-contract.test.mjs +8 -8
- package/test/r191-release-contract.test.mjs +10 -10
- package/test/r192-release-identity.test.mjs +9 -9
- package/test/r193-release-identity.test.mjs +21 -21
- 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 +10 -10
- package/test/r194-release-readiness.test.mjs +3 -3
- package/test/r194-windows-gate.test.mjs +8 -8
- package/test/r206-release-contract.test.mjs +14 -14
- 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
|
@@ -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
|
|
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=
|
|
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=
|
|
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
|
@@ -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.
|
|
74
|
-
assert.equal(typeof approvedRoot, 'string', '
|
|
75
|
-
assert.ok(path.isAbsolute(approvedRoot), '
|
|
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
|
|
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.
|
|
18
|
-
assert.equal(release.train,'
|
|
19
|
-
assert.equal(matrix.train,'
|
|
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,'
|
|
22
|
-
assert.match(release.source_predecessor.source_path,/
|
|
23
|
-
assert.equal(release.source_predecessor.manifest_status,'
|
|
24
|
-
assert.equal(release.runtime_predecessor.version,'0.15.
|
|
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,'
|
|
20
|
-
assert.equal(matrix.train,'
|
|
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,'
|
|
23
|
-
assert.match(release.source_predecessor.source_path,/
|
|
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,
|
|
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.
|
|
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.
|
|
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.
|
|
12
|
-
assert.equal(release.runtime_predecessor.release_id,'v0.15.
|
|
13
|
-
assert.equal(release.runtime_predecessor.manifest_sha256,'
|
|
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.
|
|
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.
|
|
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,'
|
|
24
|
-
assert.equal(matrix.train,'
|
|
25
|
-
assert.equal(bom.serialNumber,'urn:cdx:deadbyte-mcp:
|
|
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.
|
|
28
|
-
manifest_sha256:'
|
|
29
|
-
generation_manifest_sha256:'
|
|
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,'
|
|
33
|
-
assert.equal(release.source_predecessor.tarball_sha256,
|
|
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,'
|
|
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.
|
|
17
|
-
assert.equal(release.parent.version,'0.15.
|
|
18
|
-
assert.equal(release.runtime_predecessor.release_id,'v0.15.
|
|
19
|
-
assert.equal(release.parent.release_id,'v0.15.
|
|
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.
|
|
20
|
-
assert.equal(release.train,'
|
|
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,'
|
|
23
|
-
assert.equal(release.source_predecessor.tarball_sha256,
|
|
24
|
-
assert.equal(release.runtime_predecessor.release_id,'v0.15.
|
|
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.
|
|
17
|
-
assert.equal(lock.version,'0.15.
|
|
18
|
-
assert.equal(lock.packages[''].version,'0.15.
|
|
19
|
-
assert.equal(bridge.version,'0.15.
|
|
20
|
-
assert.equal(release.version,'0.15.
|
|
21
|
-
assert.equal(release.train,'
|
|
22
|
-
assert.equal(matrix.version,'0.15.
|
|
23
|
-
assert.equal(matrix.train,'
|
|
24
|
-
assert.equal(sbom.metadata.component.version,'0.15.
|
|
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,'
|
|
27
|
-
assert.equal(release.source_predecessor.manifest_sha256,'
|
|
28
|
-
assert.equal(release.source_predecessor.tarball_sha256,
|
|
29
|
-
assert.equal(release.runtime_predecessor.version,'0.15.
|
|
30
|
-
assert.equal(provenance.version,'0.15.
|
|
31
|
-
assert.equal(provenance.parent_tarball_sha256,'
|
|
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.
|
|
11
|
-
const manifest='
|
|
12
|
-
const generation='
|
|
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.
|
|
20
|
-
assert.equal(release.train,'
|
|
21
|
-
assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:
|
|
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,'
|
|
26
|
-
assert.equal(release.source_predecessor.tarball_sha256,
|
|
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,'
|
|
30
|
-
assert.equal(provenance.source_predecessor_tarball_sha256,
|
|
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.
|
|
12
|
-
assert.match(versionSource,/DEADBYTE_VERSION = '0\.15\.
|
|
13
|
-
assert.equal(release.train,'
|
|
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,
|
|
16
|
-
assert.equal(release.source_predecessor.manifest_sha256,'
|
|
17
|
-
assert.equal(release.runtime_predecessor.version,'0.15.
|
|
18
|
-
assert.equal(release.runtime_predecessor.release_id,'v0.15.
|
|
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,/
|
|
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()=>{
|