deadbyte-mcp 0.15.39 → 0.15.42

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 (100) hide show
  1. package/DEADBYTE-MCP.cmd +8 -4
  2. package/MANIFEST.SHA256 +99 -45
  3. package/PROVENANCE.json +90 -20
  4. package/README.txt +39 -18
  5. package/RELEASE.json +85 -20
  6. package/SBOM.cdx.json +2 -2
  7. package/TEST-MATRIX.json +134 -34
  8. package/bridge/package.json +1 -1
  9. package/controller/deadbyte-controller.ps1 +132 -12
  10. package/controller/deadbyte-process-policy.json +4 -4
  11. package/docs/R64-EVIDENCE.json +95 -0
  12. package/docs/R64-REFERENCE-GAP-MATRIX.json +98 -0
  13. package/docs/R64-SCOPE.json +41 -0
  14. package/docs/R65-AUTHORITY-CONTINUITY-DESIGN.json +27 -0
  15. package/docs/R65-REFERENCE-GAP-MATRIX.json +22 -0
  16. package/package.json +7 -4
  17. package/scripts/deploy-r48.mjs +123 -7
  18. package/scripts/gate-windows-r63-prepublish.ps1 +45 -0
  19. package/scripts/gate-windows-r64-prepublish.ps1 +68 -0
  20. package/scripts/gate-windows-r65-prepublish.ps1 +65 -0
  21. package/scripts/npm-publication-r65.mjs +139 -0
  22. package/scripts/npm-release-r48.mjs +62 -37
  23. package/scripts/r64-predecessor-reproducer.mjs +32 -0
  24. package/scripts/r64-read-benchmark.mjs +84 -0
  25. package/scripts/r65-canonical-full.mjs +45 -0
  26. package/scripts/r65-focused.mjs +37 -0
  27. package/scripts/verify-r65-parent-source.mjs +75 -0
  28. package/src/activation-continuity-engine-r65.mjs +225 -0
  29. package/src/activation-lock-r65.mjs +155 -0
  30. package/src/activation-preflight-r65.mjs +197 -0
  31. package/src/authority-continuity-r65.mjs +541 -0
  32. package/src/authority-epoch-cli-r65.mjs +10 -0
  33. package/src/autonomous-policy.mjs +7 -3
  34. package/src/coding-plane.mjs +12 -3
  35. package/src/compact-gateway-mcp-tools.mjs +1 -1
  36. package/src/deadbyte-cli.mjs +16 -2
  37. package/src/desktop-policy-r40.mjs +6 -3
  38. package/src/doctor-transactions-r58.mjs +1 -1
  39. package/src/host-plane.mjs +9 -3
  40. package/src/machine-fs-mcp-tools.mjs +1 -1
  41. package/src/machine-fs.mjs +7 -4
  42. package/src/process-policy.mjs +7 -4
  43. package/src/remote-authority.mjs +20 -1
  44. package/src/runtime-update.mjs +15 -5
  45. package/src/version.mjs +1 -1
  46. package/test/audit-context.test.mjs +15 -4
  47. package/test/autonomous-local-supervisor.test.mjs +7 -6
  48. package/test/autonomous-supervisor-integration.test.mjs +8 -7
  49. package/test/capability-resolver.test.mjs +11 -5
  50. package/test/codex-autonomous-r44.test.mjs +7 -6
  51. package/test/coding-observation.test.mjs +4 -3
  52. package/test/commander-real-parity-r47.test.mjs +5 -4
  53. package/test/commander-torture-r47.test.mjs +5 -4
  54. package/test/desktop-policy-r40.test.mjs +6 -4
  55. package/test/desktop-runtime-r40.test.mjs +8 -3
  56. package/test/host-inline-r45.test.mjs +4 -3
  57. package/test/machine-fs-runtime.test.mjs +4 -3
  58. package/test/process-longrun-r36.test.mjs +3 -2
  59. package/test/process-policy.test.mjs +10 -6
  60. package/test/process-runtime.test.mjs +9 -6
  61. package/test/r52-host-revocation.test.mjs +1 -0
  62. package/test/r59-tool-surface-compat.test.mjs +14 -4
  63. package/test/r62-release-contract.test.mjs +2 -1
  64. package/test/r63-one-shot-coherence.test.mjs +38 -0
  65. package/test/r63-release-contract.test.mjs +59 -0
  66. package/test/r64-machine-fs-large-read.test.mjs +136 -0
  67. package/test/r64-release-contract.test.mjs +52 -0
  68. package/test/r65-activation-lock-recovery.test.mjs +72 -0
  69. package/test/r65-activation-lock.test.mjs +59 -0
  70. package/test/r65-activation-orchestration.test.mjs +179 -0
  71. package/test/r65-activation-preflight.test.mjs +35 -0
  72. package/test/r65-authority-continuity-decision.test.mjs +58 -0
  73. package/test/r65-authority-durable-policy-binding.test.mjs +34 -0
  74. package/test/r65-authority-epoch-cli.test.mjs +125 -0
  75. package/test/r65-authority-epoch-races.test.mjs +87 -0
  76. package/test/r65-authority-epoch-recovery.test.mjs +82 -0
  77. package/test/r65-authority-epoch-store.test.mjs +94 -0
  78. package/test/r65-authority-fixture.mjs +41 -0
  79. package/test/r65-authority-grant-capture.test.mjs +37 -0
  80. package/test/r65-authority-observation-epoch.test.mjs +25 -0
  81. package/test/r65-authority-policy-envelope.test.mjs +46 -0
  82. package/test/r65-authority-restored-safe.test.mjs +75 -0
  83. package/test/r65-authority-runtime-epoch.test.mjs +115 -0
  84. package/test/r65-authority-runtime-policy-binding.test.mjs +29 -0
  85. package/test/r65-authority-test-trust.mjs +20 -0
  86. package/test/r65-cli-invocation.test.mjs +38 -0
  87. package/test/r65-controller-authority-epoch-live.test.mjs +100 -0
  88. package/test/r65-controller-authority-epoch.test.mjs +37 -0
  89. package/test/r65-deploy-preflight.test.mjs +55 -0
  90. package/test/r65-epoch-native-activation-integration.test.mjs +141 -0
  91. package/test/r65-epoch-native-continuity-engine.test.mjs +112 -0
  92. package/test/r65-epoch-native-cross-plane.test.mjs +95 -0
  93. package/test/r65-legacy-authority-migration.test.mjs +63 -0
  94. package/test/r65-legacy-auto-restore-rejection.test.mjs +17 -0
  95. package/test/r65-npm-publication.test.mjs +114 -0
  96. package/test/r65-parent-source-verifier.test.mjs +63 -0
  97. package/test/r65-release-contract.test.mjs +74 -0
  98. package/test/r65-transaction-precondition.test.mjs +36 -0
  99. package/test/remote-session-cli.test.mjs +13 -11
  100. package/test/standing-grants.test.mjs +20 -4
@@ -0,0 +1,125 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {mkdtemp,mkdir,rm,writeFile,readFile} from 'node:fs/promises';
4
+ import {createHash,generateKeyPairSync} from 'node:crypto';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+
8
+ const epoch=await import('../src/authority-continuity-r65.mjs');
9
+
10
+ async function prepare(root){
11
+ const runtime=path.join(root,'runtime'),trust=path.join(root,'trust');
12
+ await mkdir(runtime,{recursive:true});await mkdir(trust,{recursive:true});
13
+ const {privateKey,publicKey}=generateKeyPairSync('ed25519');
14
+ await writeFile(path.join(trust,'ed25519-private.pem'),privateKey.export({format:'pem',type:'pkcs8'}));
15
+ await writeFile(path.join(trust,'ed25519-public.pem'),publicKey.export({format:'pem',type:'spki'}));
16
+ const policyFile=path.join(root,'coding-policy.json');
17
+ const policyBytes=Buffer.from(JSON.stringify({schema:'deadbyte.coding-policy.v1',enabled:true,
18
+ lease_file:path.join(runtime,'coding-grant.json'),evidence_dir:path.join(root,'evidence'),
19
+ max_read_bytes:4096,max_write_bytes:4096,roots:{core:{path:path.join(root,'project'),read:true,write:true,exec:false,deny_paths:[]}},commands:{}}));
20
+ await writeFile(policyFile,policyBytes);
21
+ return {runtime,policyFile,policyBytes,policySha:createHash('sha256').update(policyBytes).digest('hex')};
22
+ }
23
+
24
+ test('authority epoch command dispatcher binds grant then makes explicit revoke win over stale grant bytes',async()=>{
25
+ assert.equal(typeof epoch.authorityEpochCliMain,'function','R65 authority epoch command dispatcher is missing');
26
+ const dir=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-cli-'));
27
+ try{
28
+ const {runtime,policyFile,policySha}=await prepare(dir);
29
+ const grantFile=path.join(runtime,'coding-grant.json');
30
+ const grant={schema:'deadbyte.coding-grant.v2',policy_sha256:policySha,instance_nonce:'b'.repeat(64),root_ids:['core'],granted_at_utc:'2026-10-06T00:00:00Z'};
31
+ await writeFile(grantFile,JSON.stringify(grant));
32
+ await assert.rejects(()=>epoch.authorityEpochCliMain(['grant','--plane','coding','--grant-file',grantFile]),/policy.file.*required/i);
33
+
34
+ const before=await epoch.authorityEpochCliMain(['status','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
35
+ assert.equal(before.trusted,false);
36
+
37
+ const armed=await epoch.authorityEpochCliMain(['grant','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
38
+ assert.equal(armed.action,'grant');
39
+
40
+ const trusted=await epoch.authorityEpochCliMain(['status','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
41
+ assert.equal(trusted.trusted,true);
42
+
43
+ const revoked=await epoch.authorityEpochCliMain(['user-revoke','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
44
+ assert.equal(revoked.action,'user_revoke');
45
+
46
+ const stale=await epoch.authorityEpochCliMain(['status','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
47
+ assert.equal(stale.trusted,false);
48
+ assert.equal(stale.reason,'epoch-revoked');
49
+ }finally{await rm(dir,{recursive:true,force:true});}
50
+ });
51
+
52
+ test('fabricated unsigned epoch cannot grant standing authority',async()=>{
53
+ const dir=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-forgery-'));
54
+ try{
55
+ const {runtime,policyFile,policySha}=await prepare(dir);
56
+ const grantFile=path.join(runtime,'coding-grant.json');
57
+ const grant={schema:'deadbyte.coding-grant.v2',policy_sha256:policySha,instance_nonce:'b'.repeat(64),root_ids:['core'],granted_at_utc:'2026-10-06T00:00:00Z'};
58
+ await writeFile(grantFile,JSON.stringify(grant));
59
+ const revoked=await epoch.authorityEpochCliMain(['user-revoke','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
60
+ const epochDir=path.join(runtime,'authority-epochs','coding');
61
+ const headPath=path.join(epochDir,'head.json');
62
+ const head=JSON.parse(await readFile(headPath,'utf8'));
63
+ const eventPath=path.join(epochDir,'events',head.event_file);
64
+ const event=JSON.parse(await readFile(eventPath,'utf8'));
65
+ event.action='grant';
66
+ const bytes=Buffer.from(JSON.stringify(event));
67
+ const forgedHash=createHash('sha256').update(bytes).digest('hex');
68
+ const forgedName=`${String(head.seq).padStart(16,'0')}-${forgedHash}.json`;
69
+ await writeFile(path.join(epochDir,'events',forgedName),bytes);
70
+ head.action='grant';head.event_sha256=forgedHash;head.event_file=forgedName;
71
+ await writeFile(headPath,JSON.stringify(head));
72
+ const observed=await epoch.authorityEpochCliMain(['status','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
73
+ assert.equal(observed.trusted,false,'hash-only epoch must not authorize a forged grant');
74
+ assert.equal(revoked.action,'user_revoke');
75
+ }finally{await rm(dir,{recursive:true,force:true});}
76
+ });
77
+
78
+ test('replaying an earlier genuinely signed grant head cannot undo a later revoke',async()=>{
79
+ const dir=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-replay-'));
80
+ try{
81
+ const {runtime,policyFile,policySha}=await prepare(dir);
82
+ const grantFile=path.join(runtime,'coding-grant.json');
83
+ const grant={schema:'deadbyte.coding-grant.v2',policy_sha256:policySha,instance_nonce:'b'.repeat(64),root_ids:['core'],granted_at_utc:'2026-10-06T00:00:00Z'};
84
+ await writeFile(grantFile,JSON.stringify(grant));
85
+ await epoch.authorityEpochCliMain(['grant','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
86
+ const headPath=path.join(runtime,'authority-epochs','coding','head.json');
87
+ const oldHead=await readFile(headPath);
88
+ await epoch.authorityEpochCliMain(['user-revoke','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
89
+ await writeFile(headPath,oldHead);
90
+ const observed=await epoch.authorityEpochCliMain(['status','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
91
+ assert.equal(observed.trusted,false,'a signed but stale head must not restore authority');
92
+ }finally{await rm(dir,{recursive:true,force:true});}
93
+ });
94
+
95
+
96
+ test('transaction restore CLI requires and preserves full continuity binding',async()=>{
97
+ const dir=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-cli-restore-'));
98
+ try{
99
+ const {runtime,policyFile,policyBytes,policySha}=await prepare(dir);
100
+ const grantFile=path.join(runtime,'coding-grant.json');
101
+ const oldGrant={schema:'deadbyte.coding-grant.v2',policy_sha256:policySha,instance_nonce:'c'.repeat(64),root_ids:['core'],granted_at_utc:'2026-10-07T00:00:00Z'};
102
+ const oldBytes=Buffer.from(JSON.stringify(oldGrant));
103
+ await writeFile(grantFile,oldBytes);
104
+ const granted=await epoch.authorityEpochCliMain(['grant','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
105
+ const revoked=await epoch.authorityEpochCliMain(['transaction-revoke','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile,
106
+ '--update-id','r65-cli-restore','--expected-head',granted.event_sha256]);
107
+ const newGrant={...oldGrant,instance_nonce:'d'.repeat(64),granted_at_utc:'2026-10-07T00:01:00Z'};
108
+ await writeFile(grantFile,JSON.stringify(newGrant));
109
+ await assert.rejects(()=>epoch.authorityEpochCliMain(['transaction-restore','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile,
110
+ '--update-id','r65-cli-restore','--expected-head',revoked.event_sha256]),/restore binding/i);
111
+ const envelope=epoch.deriveSecurityEnvelope('coding',JSON.parse(policyBytes));
112
+ const priorGrantSha=createHash('sha256').update(oldBytes).digest('hex');
113
+ const args=['transaction-restore','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile,
114
+ '--update-id','r65-cli-restore','--expected-head',revoked.event_sha256,
115
+ '--prior-grant-sha256',priorGrantSha,'--prior-grant-nonce',oldGrant.instance_nonce,
116
+ '--predecessor-policy-envelope',envelope.sha256,'--successor-policy-envelope',envelope.sha256,
117
+ '--candidate-manifest','e'.repeat(64),'--continuity-subject','f'.repeat(64)];
118
+ const restored=await epoch.authorityEpochCliMain(args);
119
+ assert.equal(restored.action,'transaction_restore');
120
+ assert.equal(restored.restore_binding.prior_grant_sha256,priorGrantSha);
121
+ assert.equal(restored.restore_binding.candidate_manifest_sha256,'e'.repeat(64));
122
+ const status=await epoch.authorityEpochCliMain(['status','--plane','coding','--grant-file',grantFile,'--policy-file',policyFile]);
123
+ assert.equal(status.trusted,true);
124
+ }finally{await rm(dir,{recursive:true,force:true});}
125
+ });
@@ -0,0 +1,87 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {createHash} from 'node:crypto';
4
+ import {mkdtemp,rm} from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import {createAuthorityEpochStore} from '../src/authority-continuity-r65.mjs';
8
+ import {prepareAuthorityTestTrust} from './r65-authority-test-trust.mjs';
9
+
10
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
11
+ function restoreBinding(oldGrant,oldNonce){return {prior_grant_sha256:sha(oldGrant),prior_grant_instance_nonce:oldNonce,
12
+ predecessor_policy_envelope_sha256:'1'.repeat(64),successor_policy_envelope_sha256:'2'.repeat(64),
13
+ candidate_manifest_sha256:'3'.repeat(64),continuity_subject_sha256:'4'.repeat(64)};}
14
+
15
+ function grantBytes(nonce){
16
+ return Buffer.from(JSON.stringify({
17
+ schema:'deadbyte.coding-grant.v2',policy_sha256:'a'.repeat(64),
18
+ instance_nonce:nonce,root_ids:['core'],granted_at_utc:'2026-10-06T00:00:00Z'
19
+ }));
20
+ }
21
+
22
+ test('transaction authority mutations require CAS ownership and user revoke wins',async()=>{
23
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-race-'));
24
+ try{
25
+ const store=createAuthorityEpochStore({runtimeDir:await prepareAuthorityTestTrust(root)});
26
+ const oldNonce='b'.repeat(64),oldGrant=grantBytes(oldNonce);
27
+ const granted=await store.append({plane:'coding',action:'grant',grantBytes:oldGrant,grantInstanceNonce:oldNonce,updateId:null});
28
+
29
+ await assert.rejects(
30
+ ()=>store.append({plane:'coding',action:'transaction_revoke',grantBytes:oldGrant,grantInstanceNonce:oldNonce,updateId:'update-a'}),
31
+ /compare-and-swap|expected head/i
32
+ );
33
+
34
+ const tx=await store.append({plane:'coding',action:'transaction_revoke',grantBytes:oldGrant,grantInstanceNonce:oldNonce,
35
+ updateId:'update-a',expectedHeadSha256:granted.event_sha256});
36
+ assert.equal(tx.action,'transaction_revoke');
37
+
38
+ const user=await store.append({plane:'coding',action:'user_revoke',grantBytes:oldGrant,grantInstanceNonce:oldNonce,updateId:null});
39
+ assert.equal(user.action,'user_revoke');
40
+
41
+ const newNonce='c'.repeat(64),newGrant=grantBytes(newNonce);
42
+ await assert.rejects(
43
+ ()=>store.append({plane:'coding',action:'transaction_restore',grantBytes:newGrant,grantInstanceNonce:newNonce,
44
+ updateId:'update-a',expectedHeadSha256:tx.event_sha256,restoreBinding:restoreBinding(oldGrant,oldNonce)}),
45
+ /compare-and-swap conflict/
46
+ );
47
+ assert.equal((await store.readHead({plane:'coding'})).event_sha256,user.event_sha256);
48
+ }finally{await rm(root,{recursive:true,force:true});}
49
+ });
50
+
51
+ test('transaction restore requires owning revoke and a fresh nonce',async()=>{
52
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-restore-'));
53
+ try{
54
+ const store=createAuthorityEpochStore({runtimeDir:await prepareAuthorityTestTrust(root)});
55
+ const oldNonce='d'.repeat(64),oldGrant=grantBytes(oldNonce);
56
+ const granted=await store.append({plane:'coding',action:'grant',grantBytes:oldGrant,grantInstanceNonce:oldNonce,updateId:null});
57
+ const tx=await store.append({plane:'coding',action:'transaction_revoke',grantBytes:oldGrant,grantInstanceNonce:oldNonce,
58
+ updateId:'update-a',expectedHeadSha256:granted.event_sha256});
59
+
60
+ await assert.rejects(
61
+ ()=>store.append({plane:'coding',action:'transaction_restore',grantBytes:oldGrant,grantInstanceNonce:oldNonce,
62
+ updateId:'update-a',expectedHeadSha256:tx.event_sha256}),
63
+ /restore binding/i
64
+ );
65
+ await assert.rejects(
66
+ ()=>store.append({plane:'coding',action:'transaction_restore',grantBytes:oldGrant,grantInstanceNonce:oldNonce,
67
+ updateId:'update-a',expectedHeadSha256:tx.event_sha256,restoreBinding:restoreBinding(oldGrant,oldNonce)}),
68
+ /fresh nonce|resurrect/i
69
+ );
70
+
71
+ const foreignNonce='e'.repeat(64),foreignGrant=grantBytes(foreignNonce);
72
+ await assert.rejects(
73
+ ()=>store.append({plane:'coding',action:'transaction_restore',grantBytes:foreignGrant,grantInstanceNonce:foreignNonce,
74
+ updateId:'update-b',expectedHeadSha256:tx.event_sha256,restoreBinding:restoreBinding(oldGrant,oldNonce)}),
75
+ /owner|update/i
76
+ );
77
+
78
+ const newNonce='f'.repeat(64),newGrant=grantBytes(newNonce);
79
+ const binding=restoreBinding(oldGrant,oldNonce);
80
+ const restored=await store.append({plane:'coding',action:'transaction_restore',grantBytes:newGrant,grantInstanceNonce:newNonce,
81
+ updateId:'update-a',expectedHeadSha256:tx.event_sha256,restoreBinding:binding});
82
+ assert.equal(restored.action,'transaction_restore');
83
+ assert.equal(restored.grant_instance_nonce,newNonce);
84
+ assert.deepEqual(restored.restore_binding,binding);
85
+ assert.equal((await store.verifyGrant({plane:'coding',grantBytes:newGrant,grantInstanceNonce:newNonce})).trusted,true);
86
+ }finally{await rm(root,{recursive:true,force:true});}
87
+ });
@@ -0,0 +1,82 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {mkdtemp,mkdir,rm,writeFile} from 'node:fs/promises';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import {createAuthorityEpochStore} from '../src/authority-continuity-r65.mjs';
7
+ import {prepareAuthorityTestTrust} from './r65-authority-test-trust.mjs';
8
+
9
+ function grantBytes(nonce){
10
+ return Buffer.from(JSON.stringify({
11
+ schema:'deadbyte.coding-grant.v2',policy_sha256:'a'.repeat(64),
12
+ instance_nonce:nonce,root_ids:['core'],granted_at_utc:'2026-10-06T00:00:00Z'
13
+ }));
14
+ }
15
+
16
+ test('dead-owner epoch lock is recovered but a live-owner lock is never stolen',async()=>{
17
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-lock-'));
18
+ try{
19
+ const runtime=await prepareAuthorityTestTrust(root);
20
+ const dir=path.join(runtime,'authority-epochs','coding');
21
+ await mkdir(dir,{recursive:true});
22
+ await writeFile(path.join(dir,'.lock'),JSON.stringify({schema:'deadbyte.authority-epoch-lock.r65.v1',pid:2147483647,token:'dead',created_at_utc:'2026-10-06T00:00:00Z'}));
23
+ const store=createAuthorityEpochStore({runtimeDir:runtime});
24
+ const nonce='1'.repeat(64),grant=grantBytes(nonce);
25
+ const head=await store.append({plane:'coding',action:'grant',grantBytes:grant,grantInstanceNonce:nonce,updateId:null});
26
+ assert.equal(head.seq,1);
27
+
28
+ await writeFile(path.join(dir,'.lock'),JSON.stringify({schema:'deadbyte.authority-epoch-lock.r65.v1',pid:process.pid,token:'live',created_at_utc:new Date().toISOString()}));
29
+ const nextNonce='2'.repeat(64),nextGrant=grantBytes(nextNonce);
30
+ await assert.rejects(
31
+ ()=>store.append({plane:'coding',action:'grant',grantBytes:nextGrant,grantInstanceNonce:nextNonce,updateId:null}),
32
+ /mutation locked/
33
+ );
34
+ }finally{await rm(root,{recursive:true,force:true});}
35
+ });
36
+
37
+ test('transaction revoke remains authoritative even if stale grant bytes survive a crash',async()=>{
38
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-revoke-crash-'));
39
+ try{
40
+ const store=createAuthorityEpochStore({runtimeDir:await prepareAuthorityTestTrust(root)});
41
+ const nonce='3'.repeat(64),grant=grantBytes(nonce);
42
+ const armed=await store.append({plane:'coding',action:'grant',grantBytes:grant,grantInstanceNonce:nonce,updateId:null});
43
+ const revoked=await store.append({plane:'coding',action:'transaction_revoke',grantBytes:grant,grantInstanceNonce:nonce,
44
+ updateId:'update-crash',expectedHeadSha256:armed.event_sha256});
45
+ assert.equal(revoked.action,'transaction_revoke');
46
+ const stale=await store.verifyGrant({plane:'coding',grantBytes:grant,grantInstanceNonce:nonce});
47
+ assert.equal(stale.trusted,false);
48
+ assert.equal(stale.reason,'epoch-revoked');
49
+ }finally{await rm(root,{recursive:true,force:true});}
50
+ });
51
+
52
+ test('prepared successor grant cannot become trusted before transaction restore commits',async()=>{
53
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-restore-crash-'));
54
+ try{
55
+ const store=createAuthorityEpochStore({runtimeDir:await prepareAuthorityTestTrust(root)});
56
+ const oldNonce='4'.repeat(64),oldGrant=grantBytes(oldNonce);
57
+ const armed=await store.append({plane:'coding',action:'grant',grantBytes:oldGrant,grantInstanceNonce:oldNonce,updateId:null});
58
+ await store.append({plane:'coding',action:'transaction_revoke',grantBytes:oldGrant,grantInstanceNonce:oldNonce,
59
+ updateId:'update-crash',expectedHeadSha256:armed.event_sha256});
60
+
61
+ const newNonce='5'.repeat(64),newGrant=grantBytes(newNonce);
62
+ const prepared=await store.verifyGrant({plane:'coding',grantBytes:newGrant,grantInstanceNonce:newNonce});
63
+ assert.equal(prepared.trusted,false);
64
+ assert.match(prepared.reason,/mismatch|revoked/);
65
+ }finally{await rm(root,{recursive:true,force:true});}
66
+ });
67
+
68
+ test('corrupt durable head fails closed instead of trusting grant bytes',async()=>{
69
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-corrupt-'));
70
+ try{
71
+ const runtime=await prepareAuthorityTestTrust(root);
72
+ const dir=path.join(runtime,'authority-epochs','coding');
73
+ await mkdir(dir,{recursive:true});
74
+ await writeFile(path.join(dir,'head.json'),'{broken');
75
+ const store=createAuthorityEpochStore({runtimeDir:runtime});
76
+ const nonce='6'.repeat(64),grant=grantBytes(nonce);
77
+ const verdict=await store.verifyGrant({plane:'coding',grantBytes:grant,grantInstanceNonce:nonce});
78
+ assert.equal(verdict.trusted,false);
79
+ assert.match(verdict.reason,/head invalid/);
80
+ await assert.rejects(()=>store.readHead({plane:'coding'}),/head invalid/);
81
+ }finally{await rm(root,{recursive:true,force:true});}
82
+ });
@@ -0,0 +1,94 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {createHash} from 'node:crypto';
4
+ import {mkdtemp,mkdir,readFile,rm,writeFile} from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import {createAuthorityEpochStore} from '../src/authority-continuity-r65.mjs';
8
+ import {prepareAuthorityTestTrust} from './r65-authority-test-trust.mjs';
9
+
10
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
11
+
12
+ async function fixture(run){
13
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-canonical-epoch-'));
14
+ try{
15
+ const runtime=await prepareAuthorityTestTrust(root);
16
+ const workspace=path.join(root,'workspace');await mkdir(workspace,{recursive:true});
17
+ const grantFile=path.join(runtime,'process-grant.json');
18
+ const policy={
19
+ schema:'deadbyte.process-policy.v1',enabled:true,grant_file:grantFile,
20
+ state_dir:path.join(root,'evidence','process'),
21
+ native_host:{path:'C:\\slot\\host.exe',sha256:'a'.repeat(64)},
22
+ roots:{core:{path:workspace,deny_paths:[]}},
23
+ profiles:{ping:{executable:'C:\\Windows\\cmd.exe',executable_sha256:'b'.repeat(64),
24
+ root_ids:['core'],prefix_args:['/d'],max_input_bytes:4096}}
25
+ };
26
+ const policyBytes=Buffer.from(JSON.stringify(policy));
27
+ const grant={schema:'deadbyte.process-grant.v1',policy_sha256:sha(policyBytes),instance_nonce:'c'.repeat(64),
28
+ profile_ids:['ping'],root_ids:['core'],granted_at_utc:'2026-10-07T00:00:00Z'};
29
+ const grantBytes=Buffer.from(JSON.stringify(grant));
30
+ const store=createAuthorityEpochStore({runtimeDir:runtime,policyBytes});
31
+ return await run({root,runtime,policyBytes,grant,grantBytes,store});
32
+ }finally{await rm(root,{recursive:true,force:true});}
33
+ }
34
+
35
+ function restoreBinding(oldGrant,oldNonce){
36
+ return {prior_grant_sha256:sha(oldGrant),prior_grant_instance_nonce:oldNonce,
37
+ predecessor_policy_envelope_sha256:'1'.repeat(64),successor_policy_envelope_sha256:'2'.repeat(64),
38
+ candidate_manifest_sha256:'3'.repeat(64),continuity_subject_sha256:'4'.repeat(64)};
39
+ }
40
+
41
+ test('canonical durable store trusts only the exact signed grant head',()=>fixture(async f=>{
42
+ const head=await f.store.append({plane:'process',action:'grant',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce});
43
+ const verified=await f.store.verifyGrant({plane:'process',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce,policyBytes:f.policyBytes});
44
+ assert.equal(verified.trusted,true);
45
+ assert.equal(verified.event_sha256,head.event_sha256);
46
+ const changed={...f.grant,instance_nonce:'d'.repeat(64)},changedBytes=Buffer.from(JSON.stringify(changed));
47
+ assert.equal((await f.store.verifyGrant({plane:'process',grantBytes:changedBytes,grantInstanceNonce:changed.instance_nonce,policyBytes:f.policyBytes})).trusted,false);
48
+ }));
49
+
50
+ test('committed user revoke makes stale grant bytes untrusted',()=>fixture(async f=>{
51
+ await f.store.append({plane:'process',action:'grant',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce});
52
+ await f.store.append({plane:'process',action:'user_revoke',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce});
53
+ const verified=await f.store.verifyGrant({plane:'process',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce,policyBytes:f.policyBytes});
54
+ assert.equal(verified.trusted,false);
55
+ assert.equal(verified.action,'user_revoke');
56
+ }));
57
+
58
+ test('stale transaction CAS cannot overwrite a later user revoke',()=>fixture(async f=>{
59
+ const granted=await f.store.append({plane:'process',action:'grant',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce});
60
+ const tx=await f.store.append({plane:'process',action:'transaction_revoke',grantBytes:f.grantBytes,
61
+ grantInstanceNonce:f.grant.instance_nonce,updateId:'r65-store-test',expectedHeadSha256:granted.event_sha256});
62
+ await f.store.append({plane:'process',action:'user_revoke',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce});
63
+ const nextNonce='e'.repeat(64),nextGrant=Buffer.from(JSON.stringify({...f.grant,instance_nonce:nextNonce}));
64
+ await assert.rejects(()=>f.store.append({plane:'process',action:'transaction_restore',grantBytes:nextGrant,
65
+ grantInstanceNonce:nextNonce,updateId:'r65-store-test',expectedHeadSha256:tx.event_sha256,
66
+ restoreBinding:restoreBinding(f.grantBytes,f.grant.instance_nonce)}),/compare-and-swap conflict/);
67
+ }));
68
+
69
+ test('replaying an older signed head fails closed when a later event remains',()=>fixture(async f=>{
70
+ await f.store.append({plane:'process',action:'grant',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce});
71
+ const epochDir=path.join(f.runtime,'authority-epochs','process'),oldHead=await readFile(path.join(epochDir,'head.json'));
72
+ await f.store.append({plane:'process',action:'user_revoke',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce});
73
+ await writeFile(path.join(epochDir,'head.json'),oldHead);
74
+ const verified=await f.store.verifyGrant({plane:'process',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce,policyBytes:f.policyBytes});
75
+ assert.equal(verified.trusted,false);
76
+ assert.match(String(verified.reason),/replay|incomplete|head/i);
77
+ }));
78
+
79
+ test('transaction restore requires a fresh nonce and becomes the trusted head',()=>fixture(async f=>{
80
+ const updateId='r65-store-restore';
81
+ const granted=await f.store.append({plane:'process',action:'grant',grantBytes:f.grantBytes,grantInstanceNonce:f.grant.instance_nonce});
82
+ const revoked=await f.store.append({plane:'process',action:'transaction_revoke',grantBytes:f.grantBytes,
83
+ grantInstanceNonce:f.grant.instance_nonce,updateId,expectedHeadSha256:granted.event_sha256});
84
+ await assert.rejects(()=>f.store.append({plane:'process',action:'transaction_restore',grantBytes:f.grantBytes,
85
+ grantInstanceNonce:f.grant.instance_nonce,updateId,expectedHeadSha256:revoked.event_sha256,
86
+ restoreBinding:restoreBinding(f.grantBytes,f.grant.instance_nonce)}),/fresh nonce|resurrect/i);
87
+ const newNonce='f'.repeat(64),newGrant=Buffer.from(JSON.stringify({...f.grant,instance_nonce:newNonce}));
88
+ const restored=await f.store.append({plane:'process',action:'transaction_restore',grantBytes:newGrant,
89
+ grantInstanceNonce:newNonce,updateId,expectedHeadSha256:revoked.event_sha256,
90
+ restoreBinding:restoreBinding(f.grantBytes,f.grant.instance_nonce)});
91
+ const verified=await f.store.verifyGrant({plane:'process',grantBytes:newGrant,grantInstanceNonce:newNonce,policyBytes:f.policyBytes});
92
+ assert.equal(verified.trusted,true);
93
+ assert.equal(verified.event_sha256,restored.event_sha256);
94
+ }));
@@ -0,0 +1,41 @@
1
+ import {mkdir,readFile,readdir,writeFile} from 'node:fs/promises';
2
+ import {createHash} from 'node:crypto';
3
+ import path from 'node:path';
4
+ import {createAuthorityEpochStore} from '../src/authority-continuity-r65.mjs';
5
+ import {prepareAuthorityTestTrust} from './r65-authority-test-trust.mjs';
6
+
7
+ export async function bindStandingGrantEpoch(plane,grantFile){
8
+ const bytes=await readFile(grantFile);
9
+ const grant=JSON.parse(bytes.toString('utf8'));
10
+ if(typeof grant?.instance_nonce!=='string')throw new Error('fixture grant instance_nonce missing');
11
+ const runtimeDir=path.dirname(path.resolve(grantFile));
12
+ if(path.basename(runtimeDir).toLowerCase()!=='runtime')throw new Error('fixture grant must be under isolated stateRoot/runtime');
13
+ const stateRoot=path.dirname(runtimeDir);
14
+ await prepareAuthorityTestTrust(stateRoot);
15
+ const files=(await readdir(stateRoot,{withFileTypes:true})).filter(item=>item.isFile()&&item.name.endsWith('.json'));
16
+ if(files.length>128)throw new Error('fixture policy discovery budget exceeded');
17
+ let policyBytes=null;
18
+ for(const file of files){
19
+ const candidate=await readFile(path.join(stateRoot,file.name));
20
+ if(createHash('sha256').update(candidate).digest('hex')===grant.policy_sha256){
21
+ if(policyBytes)throw new Error('fixture policy digest ambiguous');
22
+ policyBytes=candidate;
23
+ }
24
+ }
25
+ if(!policyBytes)throw new Error(`fixture exact ${plane} policy bytes missing for standing grant`);
26
+ const store=createAuthorityEpochStore({runtimeDir,policyBytes});
27
+ const prior=await store.readHead({plane});
28
+ if(prior){
29
+ const verified=await store.verifyGrant({plane,grantBytes:bytes,grantInstanceNonce:grant.instance_nonce,policyBytes});
30
+ if(verified.trusted)return verified;
31
+ }
32
+ return store.append({plane,action:'grant',grantBytes:bytes,grantInstanceNonce:grant.instance_nonce,updateId:null});
33
+ }
34
+
35
+ export async function writeBoundStandingGrant(plane,grantFile,value,{space=0}={}){
36
+ const text=JSON.stringify(value,null,space);
37
+ await mkdir(path.dirname(path.resolve(grantFile)),{recursive:true});
38
+ await writeFile(grantFile,text);
39
+ await bindStandingGrantEpoch(plane,grantFile);
40
+ return value;
41
+ }
@@ -0,0 +1,37 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {createHash} from 'node:crypto';
4
+ import {captureStandingGrant} from '../src/authority-continuity-r65.mjs';
5
+
6
+ const digest=bytes=>createHash('sha256').update(bytes).digest('hex');
7
+ const policy={schema:'deadbyte.process-policy.v1',enabled:true,grant_file:'C:\\state\\runtime\\process-grant.json',
8
+ state_dir:'C:\\state\\evidence\\process',native_host:{path:'C:\\slot\\bin\\host.exe',sha256:'a'.repeat(64)},
9
+ roots:{core:{path:'D:\\Projects\\core',deny_paths:['secrets']}},profiles:{ping:{executable:'C:\\Windows\\cmd.exe',executable_sha256:'b'.repeat(64),root_ids:['core'],prefix_args:['/d'],max_input_bytes:4096}}};
10
+ const policyBytes=Buffer.from(JSON.stringify(policy));
11
+ const grant={schema:'deadbyte.process-grant.v1',policy_sha256:digest(policyBytes),instance_nonce:'c'.repeat(64),
12
+ profile_ids:['ping'],root_ids:['core'],granted_at_utc:'2026-10-06T00:00:00.000Z'};
13
+ const options={plane:'process',policyBytes,grantBytes:Buffer.from(JSON.stringify(grant)),
14
+ predecessor:{release_id:'v0.15.41-parent',generation_manifest_sha256:'d'.repeat(64)},
15
+ candidate:{version:'0.15.42',manifest_sha256:'e'.repeat(64)},updateId:'r65-test-1'};
16
+
17
+ test('exact standing grant capture binds policy bytes, scope, nonce and release lineage',()=>{
18
+ const record=captureStandingGrant(options);
19
+ assert.equal(record.schema,'deadbyte.authority-continuity.r65.v1');
20
+ assert.equal(record.grant_sha256,digest(options.grantBytes));
21
+ assert.equal(record.grant_instance_nonce,grant.instance_nonce);
22
+ assert.deepEqual(record.granted_scope,{profile_ids:['ping'],root_ids:['core']});
23
+ assert.equal(record.prior_policy_sha256,digest(policyBytes));
24
+ assert.equal(Object.hasOwn(record,'captured_revocation_epoch'),false);
25
+ });
26
+ test('grant with stale policy digest or out-of-policy scope is rejected',()=>{
27
+ const wrongPolicy={...grant,policy_sha256:'f'.repeat(64)};
28
+ assert.throws(()=>captureStandingGrant({...options,grantBytes:Buffer.from(JSON.stringify(wrongPolicy))}),/policy/i);
29
+ const wrongScope={...grant,root_ids:['other']};
30
+ assert.throws(()=>captureStandingGrant({...options,grantBytes:Buffer.from(JSON.stringify(wrongScope))}),/scope|root/i);
31
+ });
32
+ test('changed nonce, malformed grant and foreign candidate identity cannot become captured authority',()=>{
33
+ const wrongNonce={...grant,instance_nonce:'not-a-nonce'};
34
+ assert.throws(()=>captureStandingGrant({...options,grantBytes:Buffer.from(JSON.stringify(wrongNonce))}),/nonce/i);
35
+ assert.throws(()=>captureStandingGrant({...options,grantBytes:Buffer.from('{')}),/grant/i);
36
+ assert.throws(()=>captureStandingGrant({...options,candidate:{version:'0.15.42',manifest_sha256:'bad'}}),/candidate/i);
37
+ });
@@ -0,0 +1,25 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {parseAuthorityObservation} from '../src/remote-authority.mjs';
4
+
5
+ function observation(entry){
6
+ const authority=Object.fromEntries(['process','coding','autonomous','desktop','host'].map(plane=>[plane,{configured:true,armed:false,reason:'disarmed'}]));
7
+ authority.coding={configured:true,armed:true,reason:'standing-grant',...entry};
8
+ return {schema:'deadbyte.controller-observation.v1',state:'ONLINE',local_ready:true,
9
+ bridge:{alive:true,reason:'verified',pid:1},core:{alive:true,reason:'verified',pid:2},
10
+ cloud:{alive:true,reason:'verified',pid:3},supervisor:{running:true},authority};
11
+ }
12
+
13
+ test('R65 authority observation preserves a complete epoch identity but accepts legacy absence',()=>{
14
+ const sha='a'.repeat(64);
15
+ const parsed=parseAuthorityObservation(observation({epoch_seq:7,epoch_sha256:sha}));
16
+ assert.equal(parsed.authority.coding.epoch_seq,7);
17
+ assert.equal(parsed.authority.coding.epoch_sha256,sha);
18
+
19
+ const legacy=parseAuthorityObservation(observation({}));
20
+ assert.equal(legacy.authority.coding.epoch_seq,null);
21
+ assert.equal(legacy.authority.coding.epoch_sha256,null);
22
+
23
+ assert.throws(()=>parseAuthorityObservation(observation({epoch_seq:7})),/epoch/i);
24
+ assert.throws(()=>parseAuthorityObservation(observation({epoch_seq:0,epoch_sha256:sha})),/epoch/i);
25
+ });
@@ -0,0 +1,46 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {deriveSecurityEnvelope,compareSecurityEnvelopes} from '../src/authority-continuity-r65.mjs';
4
+
5
+ const sha='a'.repeat(64);
6
+ const base=()=>({schema:'deadbyte.process-policy.v1',enabled:true,
7
+ grant_file:'C:\\state\\runtime\\process-grant.json',state_dir:'C:\\state\\evidence\\process',
8
+ native_host:{path:'C:\\slot\\bin\\deadbyte-process-host.exe',sha256:sha},
9
+ roots:{core:{path:'D:\\Projects\\core',deny_paths:['node_modules','secrets']}},
10
+ profiles:{ping:{executable:'C:\\Windows\\System32\\cmd.exe',executable_sha256:sha,
11
+ root_ids:['core'],prefix_args:['/d'],transport:'pipe',max_args:0,max_arg_bytes:256,
12
+ max_sessions:1,max_input_bytes:4096,max_retained_output_bytes:65536,
13
+ env_allow:['PATH'],input_actions:{ping:'echo PING\r\n'}}}});
14
+ const compare=(before,after)=>compareSecurityEnvelopes('process',deriveSecurityEnvelope('process',before),deriveSecurityEnvelope('process',after));
15
+
16
+ test('identical security envelope ignores only operational grant/evidence paths',()=>{
17
+ const before=base(),after=base();after.grant_file='C:\\other\\runtime\\process-grant.json';after.state_dir='C:\\other\\evidence';
18
+ assert.equal(compare(before,after).relation,'EQUAL');
19
+ });
20
+ test('removing an unused profile is narrower',()=>{
21
+ const before=base(),after=base();before.profiles.extra={...before.profiles.ping};
22
+ assert.equal(compare(before,after).relation,'NARROWER');
23
+ });
24
+ test('added root or action widens the policy ceiling',()=>{
25
+ const before=base(),rootAdded=base(),actionAdded=base();
26
+ rootAdded.roots.extra={path:'D:\\Extra',deny_paths:[]};
27
+ actionAdded.profiles.ping.input_actions.extra='echo EXTRA\r\n';
28
+ assert.equal(compare(before,rootAdded).relation,'WIDER');
29
+ assert.equal(compare(before,actionAdded).relation,'WIDER');
30
+ });
31
+ test('relaxed deny paths or increased byte ceiling widens authority',()=>{
32
+ const before=base(),denyRelaxed=base(),larger=base();
33
+ denyRelaxed.roots.core.deny_paths=['node_modules'];larger.profiles.ping.max_input_bytes=8192;
34
+ assert.equal(compare(before,denyRelaxed).relation,'WIDER');
35
+ assert.equal(compare(before,larger).relation,'WIDER');
36
+ });
37
+ test('unproved executable or native host pin change is unverified',()=>{
38
+ const before=base(),executable=base(),host=base();
39
+ executable.profiles.ping.executable_sha256='b'.repeat(64);host.native_host.sha256='b'.repeat(64);
40
+ assert.equal(compare(before,executable).relation,'UNVERIFIED');
41
+ assert.equal(compare(before,host).relation,'UNVERIFIED');
42
+ });
43
+ test('unrecognized security fields fail closed instead of being discarded',()=>{
44
+ const unknown=base();unknown.profiles.ping.allow_arbitrary_shell=true;
45
+ assert.throws(()=>deriveSecurityEnvelope('process',unknown),/unknown|unrecognized/i);
46
+ });
@@ -0,0 +1,75 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {createHash,generateKeyPairSync} from 'node:crypto';
4
+ import {mkdtemp,mkdir,readFile,rm,writeFile} from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import {orchestrateActivation} from '../src/activation-preflight-r65.mjs';
8
+ import {createAuthorityEpochStore} from '../src/authority-continuity-r65.mjs';
9
+ import {createEpochNativeContinuityEngine} from '../src/activation-continuity-engine-r65.mjs';
10
+
11
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
12
+ const parent={release_id:'v0.15.41-parent',version:'0.15.41',manifest_sha256:'a'.repeat(64),generation_manifest_sha256:'b'.repeat(64)};
13
+ const candidate={version:'0.15.42',manifest_sha256:'c'.repeat(64)};
14
+ const ids={bridge:{alive:true,reason:'verified',pid:10},core:{alive:true,reason:'verified',pid:11},cloud:{alive:true,reason:'verified',pid:12}};
15
+ const policies={process:'1'.repeat(64),coding:'2'.repeat(64),autonomous:'3'.repeat(64),desktop:'4'.repeat(64),host:'5'.repeat(64)};
16
+ const epochEntry=(armed,seq=7,hash='f'.repeat(64))=>({configured:true,armed,reason:armed?'standing-grant':'disarmed',epoch_seq:armed?seq:null,epoch_sha256:armed?hash:null});
17
+
18
+ test('orchestrator reports RESTORED_SAFE when all restored authority is safe but not exact',async()=>{
19
+ let current={state:'ONLINE',local_ready:true,...ids,supervisor:{running:true},policy_sha256:policies,
20
+ active_release_id:parent.release_id,active_manifest_sha256:parent.manifest_sha256,active_generation_manifest_sha256:parent.generation_manifest_sha256,
21
+ authority:{process:epochEntry(true),coding:epochEntry(false),autonomous:epochEntry(false),desktop:epochEntry(false),host:epochEntry(false)}};
22
+ const continuityEngine={
23
+ capture:async({subject_sha256})=>({update_id:'r65-safe',subject_sha256,planes:['process'],records:{process:{}}}),
24
+ revoke:async()=>{current={...current,authority:{...current.authority,process:epochEntry(false)}};return {process:'TRANSACTION_REVOKED'};},
25
+ restore:async()=>{current={...current,authority:{...current.authority,process:epochEntry(true,9,'9'.repeat(64))}};
26
+ return {authority_outcomes:{process:'RESTORED_SAFE',coding:'NOT_APPLICABLE',autonomous:'NOT_APPLICABLE',desktop:'NOT_APPLICABLE',host:'NOT_APPLICABLE'},restored_nonces:{process:'8'.repeat(64)},reauth_planes:[]};}
27
+ };
28
+ const result=await orchestrateActivation({pointer:parent,expectedParent:parent,candidate,expectedCandidate:candidate,
29
+ observe:async()=>current,command:async()=>{throw new Error('generic command forbidden');},
30
+ activate:async()=>({verified:true,release_id:'v0.15.42-candidate'}),continuityEngine});
31
+ assert.equal(result.state,'ACTIVATED');
32
+ assert.equal(result.authority_continuity,'RESTORED_SAFE');
33
+ assert.equal(result.authority_outcomes.process,'RESTORED_SAFE');
34
+ });
35
+
36
+ test('engine marks a non-widening narrowed successor policy as RESTORED_SAFE',async()=>{
37
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-restored-safe-'));
38
+ try{
39
+ const state=path.join(root,'state'),runtime=path.join(state,'runtime'),trust=path.join(state,'trust'),policiesDir=path.join(root,'policies');
40
+ await mkdir(runtime,{recursive:true});await mkdir(trust,{recursive:true});await mkdir(policiesDir,{recursive:true});
41
+ const {privateKey,publicKey}=generateKeyPairSync('ed25519');
42
+ await writeFile(path.join(trust,'ed25519-private.pem'),privateKey.export({format:'pem',type:'pkcs8'}));
43
+ await writeFile(path.join(trust,'ed25519-public.pem'),publicKey.export({format:'pem',type:'spki'}));
44
+ const grantFile=path.join(runtime,'process-grant.json');
45
+ const basePolicy={schema:'deadbyte.process-policy.v1',enabled:true,grant_file:grantFile,state_dir:path.join(state,'evidence','process'),
46
+ native_host:{path:'C:\\Windows\\System32\\cmd.exe',sha256:'6'.repeat(64)},
47
+ roots:{core:{path:'D:\\Projects',deny_paths:[]},unused:{path:'D:\\Unused',deny_paths:[]}},
48
+ profiles:{safe:{executable:'C:\\Windows\\System32\\cmd.exe',executable_sha256:'7'.repeat(64),root_ids:['core'],prefix_args:['/d'],max_input_bytes:4096}}};
49
+ const nextPolicy={...basePolicy,roots:{core:basePolicy.roots.core}};
50
+ const beforeBytes=Buffer.from(JSON.stringify(basePolicy)),afterBytes=Buffer.from(JSON.stringify(nextPolicy));
51
+ const beforePath=path.join(policiesDir,'before.json'),afterPath=path.join(policiesDir,'after.json');
52
+ await writeFile(beforePath,beforeBytes);await writeFile(afterPath,afterBytes);
53
+ const grant={schema:'deadbyte.process-grant.v1',policy_sha256:sha(beforeBytes),instance_nonce:'8'.repeat(64),profile_ids:['safe'],root_ids:['core'],granted_at_utc:'2026-10-07T00:00:00Z'};
54
+ const grantBytes=Buffer.from(JSON.stringify(grant));await writeFile(grantFile,grantBytes);
55
+ const store=createAuthorityEpochStore({runtimeDir:runtime,policyBytes:beforeBytes});
56
+ const head=await store.append({plane:'process',action:'grant',grantBytes,grantInstanceNonce:grant.instance_nonce});
57
+ const engine=createEpochNativeContinuityEngine({stateRoot:state,
58
+ predecessorPolicyPaths:{process:beforePath,coding:null,autonomous:null,desktop:null,host:null},
59
+ successorPolicyPaths:async()=>({process:afterPath,coding:null,autonomous:null,desktop:null,host:null}),updateId:'r65-safe-engine'});
60
+ const observation={authority:{process:{configured:true,armed:true,reason:'standing-grant',epoch_seq:head.seq,epoch_sha256:head.event_sha256},
61
+ coding:{configured:false,armed:false,reason:'no-policy',epoch_seq:null,epoch_sha256:null},
62
+ autonomous:{configured:false,armed:false,reason:'no-policy',epoch_seq:null,epoch_sha256:null},
63
+ desktop:{configured:false,armed:false,reason:'no-policy',epoch_seq:null,epoch_sha256:null},
64
+ host:{configured:false,armed:false,reason:'no-policy',epoch_seq:null,epoch_sha256:null}}};
65
+ const subject='d'.repeat(64);
66
+ const capture=await engine.capture({observation,subject_sha256:subject,pointer:parent,expectedParent:parent,candidate,expectedCandidate:candidate});
67
+ await engine.revoke(capture);
68
+ const restored=await engine.restore({capture,successor_observation:{},activation:{verified:true,release_id:'v0.15.42-candidate'},
69
+ pointer:parent,expectedParent:parent,candidate,expectedCandidate:candidate,subject_sha256:subject});
70
+ assert.equal(restored.authority_outcomes.process,'RESTORED_SAFE');
71
+ const nextGrant=JSON.parse(await readFile(grantFile));
72
+ assert.notEqual(nextGrant.instance_nonce,grant.instance_nonce);
73
+ assert.deepEqual(nextGrant.root_ids,['core']);
74
+ }finally{await rm(root,{recursive:true,force:true});}
75
+ });