deadbyte-mcp 0.15.41 → 0.15.43

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 (89) hide show
  1. package/DEADBYTE-MCP.cmd +8 -4
  2. package/MANIFEST.SHA256 +88 -43
  3. package/PROVENANCE.json +66 -15
  4. package/README.txt +27 -18
  5. package/RELEASE.json +55 -15
  6. package/SBOM.cdx.json +2 -2
  7. package/TEST-MATRIX.json +117 -14
  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/R65-AUTHORITY-CONTINUITY-DESIGN.json +27 -0
  12. package/docs/R65-REFERENCE-GAP-MATRIX.json +22 -0
  13. package/package.json +6 -4
  14. package/scripts/deploy-r48.mjs +123 -7
  15. package/scripts/gate-windows-r65-prepublish.ps1 +65 -0
  16. package/scripts/gate-windows-r66-prepublish.ps1 +65 -0
  17. package/scripts/npm-publication-r65.mjs +139 -0
  18. package/scripts/npm-release-r48.mjs +56 -37
  19. package/scripts/r65-canonical-full.mjs +45 -0
  20. package/scripts/r65-focused.mjs +37 -0
  21. package/scripts/verify-r65-parent-source.mjs +75 -0
  22. package/src/activation-continuity-engine-r65.mjs +225 -0
  23. package/src/activation-lock-r65.mjs +155 -0
  24. package/src/activation-preflight-r65.mjs +197 -0
  25. package/src/authority-continuity-r65.mjs +541 -0
  26. package/src/authority-epoch-cli-r65.mjs +10 -0
  27. package/src/autonomous-policy.mjs +7 -3
  28. package/src/coding-plane.mjs +12 -3
  29. package/src/desktop-policy-r40.mjs +6 -3
  30. package/src/doctor-runtime-r58.mjs +3 -1
  31. package/src/doctor-transactions-r58.mjs +1 -1
  32. package/src/host-plane.mjs +9 -3
  33. package/src/process-policy.mjs +7 -4
  34. package/src/remote-authority.mjs +10 -1
  35. package/src/runtime-update.mjs +15 -5
  36. package/src/version.mjs +1 -1
  37. package/test/audit-context.test.mjs +15 -4
  38. package/test/autonomous-local-supervisor.test.mjs +7 -6
  39. package/test/autonomous-supervisor-integration.test.mjs +8 -7
  40. package/test/capability-resolver.test.mjs +11 -5
  41. package/test/codex-autonomous-r44.test.mjs +7 -6
  42. package/test/coding-observation.test.mjs +4 -3
  43. package/test/commander-real-parity-r47.test.mjs +5 -4
  44. package/test/commander-torture-r47.test.mjs +5 -4
  45. package/test/desktop-policy-r40.test.mjs +6 -4
  46. package/test/desktop-runtime-r40.test.mjs +8 -3
  47. package/test/host-inline-r45.test.mjs +4 -3
  48. package/test/machine-fs-runtime.test.mjs +4 -3
  49. package/test/process-longrun-r36.test.mjs +3 -2
  50. package/test/process-policy.test.mjs +10 -6
  51. package/test/process-runtime.test.mjs +9 -6
  52. package/test/r52-host-revocation.test.mjs +1 -0
  53. package/test/r58-doctor-runtime.test.mjs +18 -0
  54. package/test/r59-tool-surface-compat.test.mjs +1 -1
  55. package/test/r64-release-contract.test.mjs +2 -1
  56. package/test/r65-activation-lock-recovery.test.mjs +72 -0
  57. package/test/r65-activation-lock.test.mjs +59 -0
  58. package/test/r65-activation-orchestration.test.mjs +179 -0
  59. package/test/r65-activation-preflight.test.mjs +35 -0
  60. package/test/r65-authority-continuity-decision.test.mjs +58 -0
  61. package/test/r65-authority-durable-policy-binding.test.mjs +34 -0
  62. package/test/r65-authority-epoch-cli.test.mjs +125 -0
  63. package/test/r65-authority-epoch-races.test.mjs +87 -0
  64. package/test/r65-authority-epoch-recovery.test.mjs +82 -0
  65. package/test/r65-authority-epoch-store.test.mjs +94 -0
  66. package/test/r65-authority-fixture.mjs +41 -0
  67. package/test/r65-authority-grant-capture.test.mjs +37 -0
  68. package/test/r65-authority-observation-epoch.test.mjs +25 -0
  69. package/test/r65-authority-policy-envelope.test.mjs +46 -0
  70. package/test/r65-authority-restored-safe.test.mjs +75 -0
  71. package/test/r65-authority-runtime-epoch.test.mjs +115 -0
  72. package/test/r65-authority-runtime-policy-binding.test.mjs +29 -0
  73. package/test/r65-authority-test-trust.mjs +20 -0
  74. package/test/r65-cli-invocation.test.mjs +38 -0
  75. package/test/r65-controller-authority-epoch-live.test.mjs +100 -0
  76. package/test/r65-controller-authority-epoch.test.mjs +37 -0
  77. package/test/r65-deploy-preflight.test.mjs +55 -0
  78. package/test/r65-epoch-native-activation-integration.test.mjs +141 -0
  79. package/test/r65-epoch-native-continuity-engine.test.mjs +112 -0
  80. package/test/r65-epoch-native-cross-plane.test.mjs +95 -0
  81. package/test/r65-legacy-authority-migration.test.mjs +63 -0
  82. package/test/r65-legacy-auto-restore-rejection.test.mjs +17 -0
  83. package/test/r65-npm-publication.test.mjs +114 -0
  84. package/test/r65-parent-source-verifier.test.mjs +63 -0
  85. package/test/r65-release-contract.test.mjs +75 -0
  86. package/test/r65-transaction-precondition.test.mjs +36 -0
  87. package/test/r66-release-contract.test.mjs +56 -0
  88. package/test/remote-session-cli.test.mjs +6 -6
  89. package/test/standing-grants.test.mjs +20 -4
@@ -0,0 +1,75 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {readFile} from 'node:fs/promises';
4
+
5
+ const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
6
+ const json=async rel=>JSON.parse((await read(rel)).replace(/^\uFEFF/,''));
7
+ const currentPackage=await json('package.json');
8
+ const PARENT={
9
+ version:'0.15.41',
10
+ release_id:'v0.15.41-63a78ad159ad3003',
11
+ manifest_sha256:'63a78ad159ad3003db3fefafcd468bef22599c829a867f4f10a46c7a20748b3e',
12
+ generation_manifest_sha256:'19ae2efcdcde9f80c474f0e55851d4ada51c22813d3e05af03b11acb28c3fca5'
13
+ };
14
+
15
+ test('R65 release identity binds exact production R64 parent and durable authority-continuity train',{skip:currentPackage.version!=='0.15.42'},async()=>{
16
+ const [pkg,lock,bridge,release,provenance,matrix,sbom,version,gate,gaps,design]=await Promise.all([
17
+ json('package.json'),json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
18
+ json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),
19
+ read('scripts/gate-windows-r65-prepublish.ps1'),json('docs/R65-REFERENCE-GAP-MATRIX.json'),
20
+ json('docs/R65-AUTHORITY-CONTINUITY-DESIGN.json')
21
+ ]);
22
+ assert.equal(pkg.version,'0.15.42');
23
+ assert.equal(lock.version,pkg.version);
24
+ assert.equal(lock.packages[''].version,pkg.version);
25
+ assert.equal(bridge.version,pkg.version);
26
+ assert.match(version,/DEADBYTE_VERSION = '0\.15\.42'/);
27
+ assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r65-prepublish.ps1');
28
+ assert.equal(pkg.scripts['r65:focused:test'],'node scripts/r65-focused.mjs');
29
+
30
+ assert.equal(release.version,pkg.version);
31
+ assert.equal(release.train,'R65');
32
+ assert.equal(release.parent.version,PARENT.version);
33
+ assert.equal(release.parent.release_id,PARENT.release_id);
34
+ assert.equal(release.parent.manifest_sha256,PARENT.manifest_sha256);
35
+ assert.equal(release.parent.generation_manifest_sha256,PARENT.generation_manifest_sha256);
36
+ assert.deepEqual(release.runtime_predecessor,{
37
+ release_id:PARENT.release_id,
38
+ manifest_sha256:PARENT.manifest_sha256,
39
+ generation_manifest_sha256:PARENT.generation_manifest_sha256
40
+ });
41
+ assert.equal(release.source_predecessor.version,PARENT.version);
42
+ assert.equal(release.source_predecessor.manifest_file_sha256,PARENT.manifest_sha256);
43
+ assert.equal(release.source_predecessor.release_status,'PRODUCTION_RELEASED');
44
+ assert.equal(release.r65_release_control_hardening.new_public_tools,0);
45
+ assert.equal(release.r65_release_control_hardening.new_authority_scopes,0);
46
+ assert.equal(release.r65_release_control_hardening.legacy_r64_auto_restore,false);
47
+ assert.equal(release.r65_release_control_hardening.epoch_native_restore_requires_continuity_proof,true);
48
+ assert.equal(release.r65_release_control_hardening.explicit_revoke_wins,true);
49
+ assert.equal(release.r65_release_control_hardening.revoked_nonce_resurrection,false);
50
+ assert.equal(release.r65_release_control_hardening.stable_final_claim,false);
51
+
52
+ assert.equal(provenance.version,pkg.version);
53
+ assert.equal(provenance.parent_release_id,PARENT.release_id);
54
+ assert.equal(provenance.parent_manifest_sha256,PARENT.manifest_sha256);
55
+ assert.equal(provenance.parent_generation_manifest_sha256,PARENT.generation_manifest_sha256);
56
+ assert.equal(provenance.source_predecessor_version,PARENT.version);
57
+ assert.equal(provenance.source_predecessor_manifest_file_sha256,PARENT.manifest_sha256);
58
+ assert.equal(provenance.r65.production_mutations,0);
59
+ assert.equal(provenance.r65.npm_publications,0);
60
+
61
+ assert.equal(matrix.version,pkg.version);
62
+ assert.equal(matrix.train,'R65');
63
+ assert.ok(matrix.required.some(row=>row.id==='r65-focused'));
64
+ assert.ok(matrix.required.some(row=>row.id==='r65-full-regression'));
65
+ assert.equal(sbom.metadata.component.version,pkg.version);
66
+ assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r65:0.15.42');
67
+ assert.equal(gaps.decisions.length,7);
68
+ assert.equal(design.selected_method.r64_predecessor_continuity.includes('REAUTH_REQUIRED'),true);
69
+
70
+ assert.match(gate,/v0\.15\.41-63a78ad159ad3003/);
71
+ assert.match(gate,/63a78ad159ad3003db3fefafcd468bef22599c829a867f4f10a46c7a20748b3e/);
72
+ assert.match(gate,/19ae2efcdcde9f80c474f0e55851d4ada51c22813d3e05af03b11acb28c3fca5/);
73
+ assert.match(gate,/r65:focused:test/);
74
+ assert.doesNotMatch(gate,/npm\.cmd publish|--publish-only/);
75
+ });
@@ -0,0 +1,36 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {generateKeyPairSync} from 'node:crypto';
4
+ import {mkdtemp,mkdir,readFile,rm,writeFile,unlink} from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import {performSlotUpdate,verifySlotUpdateEnvelope} from '../src/runtime-update.mjs';
8
+ import {inspectDoctorTransactions} from '../src/doctor-transactions-r58.mjs';
9
+
10
+ test('deterministic candidate precondition rejection is a signed terminal phase, not unresolved residue',async()=>{
11
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-precondition-'));
12
+ try{
13
+ const state=path.join(root,'state'),trust=path.join(state,'trust');
14
+ await mkdir(trust,{recursive:true});
15
+ const {privateKey,publicKey}=generateKeyPairSync('ed25519');
16
+ await writeFile(path.join(trust,'ed25519-private.pem'),privateKey.export({type:'pkcs8',format:'pem'}));
17
+ await writeFile(path.join(trust,'ed25519-public.pem'),publicKey.export({type:'spki',format:'pem'}));
18
+ const stage=path.join(root,'missing-candidate');
19
+ let failure;
20
+ try{await performSlotUpdate({stage,developmentRoot:path.join(root,'dev'),expectedVersion:'0.15.42',expectedManifest:'a'.repeat(64),stateRoot:state});}
21
+ catch(error){failure=error;}
22
+ assert.ok(failure?.statePath,'expected isolated precondition failure evidence');
23
+ const journal=JSON.parse(await readFile(failure.statePath,'utf8'));
24
+ assert.equal(journal.phase,'precondition_rejected');
25
+ const receipt=JSON.parse(await readFile(failure.failureReceiptPath,'utf8'));
26
+ assert.equal(receipt.body.result,'PRECONDITION_REJECTED');
27
+ assert.equal(verifySlotUpdateEnvelope(receipt,publicKey),true);
28
+ const doctor=await inspectDoctorTransactions(state);
29
+ assert.equal(doctor.status,'PASS');
30
+ assert.equal(doctor.findings.at(-1).evidence.unresolved_transactions,0);
31
+ await unlink(failure.failureReceiptPath);
32
+ const missing=await inspectDoctorTransactions(state);
33
+ assert.equal(missing.status,'FAIL');
34
+ assert.ok(missing.findings.some(item=>item.evidence?.check==='missing_failure_receipt'));
35
+ }finally{await rm(root,{recursive:true,force:true});}
36
+ });
@@ -0,0 +1,56 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {readFile} from 'node:fs/promises';
4
+
5
+ const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
6
+ const json=async rel=>JSON.parse((await read(rel)).replace(/^\uFEFF/,''));
7
+ const PARENT={
8
+ version:'0.15.42',
9
+ release_id:'v0.15.42-1b4754103dd4ca43',
10
+ manifest_sha256:'1b4754103dd4ca43eb81f8e33cf188b36eee3051cb182396ccc6abe2a6e6c250',
11
+ generation_manifest_sha256:'62dc68be55ad627f8d872b8be8c1369ecca0edf08fdedc8336c9ccee2d2809fb'
12
+ };
13
+
14
+ test('R66 identity is an exact prepublish doctor hotfix of sealed R65',async()=>{
15
+ const [pkg,lock,bridge,release,provenance,matrix,sbom,version,gate]=await Promise.all([
16
+ json('package.json'),json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
17
+ json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),
18
+ read('scripts/gate-windows-r66-prepublish.ps1')
19
+ ]);
20
+ assert.equal(pkg.version,'0.15.43');
21
+ assert.equal(lock.version,pkg.version);
22
+ assert.equal(lock.packages[''].version,pkg.version);
23
+ assert.equal(bridge.version,pkg.version);
24
+ assert.match(version,/DEADBYTE_VERSION = '0\.15\.43'/);
25
+ assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r66-prepublish.ps1');
26
+ assert.match(pkg.scripts['r66:focused:test'],/test\/r58-doctor-runtime\.test\.mjs/);
27
+ assert.equal(release.version,pkg.version);
28
+ assert.equal(release.train,'R66');
29
+ for(const [key,value] of Object.entries(PARENT))assert.equal(release.parent[key],value);
30
+ assert.deepEqual(release.runtime_predecessor,{
31
+ release_id:PARENT.release_id,
32
+ manifest_sha256:PARENT.manifest_sha256,
33
+ generation_manifest_sha256:PARENT.generation_manifest_sha256
34
+ });
35
+ assert.equal(release.source_predecessor.version,PARENT.version);
36
+ assert.equal(release.source_predecessor.manifest_file_sha256,PARENT.manifest_sha256);
37
+ assert.equal(release.r66_doctor_epoch_hotfix.doctor_epoch_observation_compatibility,true);
38
+ assert.equal(release.r66_doctor_epoch_hotfix.new_public_tools,0);
39
+ assert.equal(release.r66_doctor_epoch_hotfix.new_authority_scopes,0);
40
+ assert.equal(release.r66_doctor_epoch_hotfix.prepublish_only,true);
41
+ assert.equal(provenance.version,pkg.version);
42
+ assert.equal(provenance.parent_release_id,PARENT.release_id);
43
+ assert.equal(provenance.parent_manifest_sha256,PARENT.manifest_sha256);
44
+ assert.equal(provenance.parent_generation_manifest_sha256,PARENT.generation_manifest_sha256);
45
+ assert.equal(provenance.r66.new_public_tools,0);
46
+ assert.equal(provenance.r66.new_authority_scopes,0);
47
+ assert.equal(matrix.version,pkg.version);
48
+ assert.equal(matrix.train,'R66');
49
+ assert.ok(matrix.required.some(row=>row.id==='r66-focused'));
50
+ assert.equal(sbom.metadata.component.version,pkg.version);
51
+ assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r66:0.15.43');
52
+ assert.match(gate,/v0\.15\.42-1b4754103dd4ca43/);
53
+ assert.match(gate,/62dc68be55ad627f8d872b8be8c1369ecca0edf08fdedc8336c9ccee2d2809fb/);
54
+ assert.match(gate,/r66:focused:test/);
55
+ assert.doesNotMatch(gate,/npm\.cmd publish|--publish-only/);
56
+ });
@@ -182,7 +182,7 @@ winTest('remote refuses READY when public signed MCP execution probe fails',asyn
182
182
  try{
183
183
  child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
184
184
  const output=await collect(child);
185
- const ended=await Promise.race([output.closed,sleep(6500).then(()=>({timeout:true}))]);
185
+ const ended=await Promise.race([output.closed,sleep(12000).then(()=>({timeout:true}))]);
186
186
  assert.equal(ended.timeout,undefined,'remote did not fail closed after execution probe failure');
187
187
  assert.notEqual(ended.code,0);
188
188
  assert.doesNotMatch(output.stdout,/\[READY\]|\[OK\] ONLINE/);
@@ -201,8 +201,8 @@ winTest('remote refuses READY when controller snapshot lies about Host enforceme
201
201
  try{
202
202
  child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
203
203
  const output=await collect(child);
204
- const ended=await Promise.race([output.closed,sleep(6500).then(()=>({timeout:true}))]);
205
- assert.equal(ended.timeout,undefined,'remote did not reject split authority truth');
204
+ const ended=await Promise.race([output.closed,sleep(12000).then(()=>({timeout:true}))]);
205
+ assert.equal(ended.timeout,undefined,`remote did not reject split authority truth; stdout=${output.stdout.slice(-1200)} stderr=${output.stderr.slice(-1200)} trace=${(await traceCommands(fx.trace)).join(',')}`);
206
206
  assert.notEqual(ended.code,0);
207
207
  assert.doesNotMatch(output.stdout,/\[READY\]|\[OK\] ONLINE/);
208
208
  assert.match(output.stderr,/machinetest|enforcement/i);
@@ -394,7 +394,7 @@ winTest('remote --resume replays sanitized tool-call and terminal result events
394
394
  const liveIndex=secondOutput.stdout.indexOf('[LOG] Human live timeline');
395
395
  assert.ok(callReplayIndex>=0&&resultReplayIndex>callReplayIndex&&liveIndex>resultReplayIndex,'resume ordering must be call -> result -> live tail');
396
396
  second.stdin.end();
397
- const secondEnded=await Promise.race([secondOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
397
+ const secondEnded=await Promise.race([secondOutput.closed,sleep(12000).then(()=>({timeout:true}))]);
398
398
  assert.equal(secondEnded.timeout,undefined);
399
399
  assert.equal(secondEnded.code,0,secondOutput.stderr);
400
400
  }finally{
@@ -502,8 +502,8 @@ winTest('bare remote rolls back authority and parks if one plane fails to arm',a
502
502
  try{
503
503
  const child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['ignore','pipe','pipe'],windowsHide:true});
504
504
  const output=await collect(child);
505
- const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
506
- assert.equal(ended.timeout,undefined,'failed startup did not terminate');
505
+ const ended=await Promise.race([output.closed,sleep(12000).then(()=>({timeout:true}))]);
506
+ assert.equal(ended.timeout,undefined,`failed startup did not terminate; stdout=${output.stdout.slice(-1200)} stderr=${output.stderr.slice(-1200)} trace=${(await traceCommands(fx.trace)).join(',')}`);
507
507
  assert.notEqual(ended.code,0);
508
508
  const commands=await traceCommands(fx.trace);
509
509
  assert.deepEqual(commands.slice(0,6),['status','start','status','status','armprocess','armcoding']);
@@ -1,23 +1,26 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { mkdtemp, mkdir, writeFile } from 'node:fs/promises';
3
+ import { mkdtemp, mkdir, readFile, writeFile } from 'node:fs/promises';
4
4
  import os from 'node:os';
5
5
  import path from 'node:path';
6
6
  import { loadCodingPolicy, codingSessionStatus } from '../src/coding-plane.mjs';
7
7
  import { assertAutonomousArmed, loadAutonomousPolicy, autonomousSessionStatus, recheckAutonomousAuthority } from '../src/autonomous-policy.mjs';
8
8
  import { loadHostPolicy, assertHostArmed } from '../src/host-plane.mjs';
9
9
  import { createHash } from 'node:crypto';
10
+ import { createAuthorityEpochStore } from '../src/authority-continuity-r65.mjs';
11
+ import { prepareAuthorityTestTrust } from './r65-authority-test-trust.mjs';
10
12
 
11
13
  const sha = bytes => createHash('sha256').update(bytes).digest('hex');
12
14
  const farFuture = new Date('2099-01-01T00:00:00Z');
13
15
 
14
16
  async function fixture() {
15
17
  const root = await mkdtemp(path.join(os.tmpdir(), 'deadbyte-standing-'));
18
+ await prepareAuthorityTestTrust(root);
16
19
  const project = path.join(root, 'project');
17
20
  await mkdir(project);
18
21
  const codingPath = path.join(root, 'coding.json');
19
22
  await writeFile(codingPath, JSON.stringify({ schema:'deadbyte.coding-policy.v1', enabled:true,
20
- lease_file:path.join(root,'coding-grant.json'), evidence_dir:path.join(root,'coding-evidence'),
23
+ lease_file:path.join(root,'runtime','coding-grant.json'), evidence_dir:path.join(root,'coding-evidence'),
21
24
  roots:{ project:{ path:project, read:true, write:true, exec:false, deny_paths:[] } }, commands:{} }));
22
25
  const coding = await loadCodingPolicy(codingPath);
23
26
  return { root, project, coding, codingPath };
@@ -27,6 +30,10 @@ test('coding standing grant remains armed until explicit revocation', async () =
27
30
  await writeFile(coding.lease_file, JSON.stringify({ schema:'deadbyte.coding-grant.v2',
28
31
  policy_sha256:coding.policy_sha256, instance_nonce:'a'.repeat(64), root_ids:['project'],
29
32
  granted_at_utc:'2026-09-04T00:00:00Z' }));
33
+ const codingBytes=await readFile(coding.lease_file);
34
+ await createAuthorityEpochStore({runtimeDir:path.dirname(coding.lease_file),policyBytes:await readFile(coding.policy_path)}).append({
35
+ plane:'coding',action:'grant',grantBytes:codingBytes,grantInstanceNonce:'a'.repeat(64),updateId:null
36
+ });
30
37
  const status = await codingSessionStatus(coding, farFuture);
31
38
  assert.equal(status.armed, true);
32
39
  assert.equal(status.reason, 'standing-grant');
@@ -37,13 +44,17 @@ test('autonomous standing grant remains armed until explicit revocation', async
37
44
  const { root, coding } = await fixture();
38
45
  const policyPath = path.join(root, 'autonomous.json');
39
46
  await writeFile(policyPath, JSON.stringify({ schema:'deadbyte.autonomous-policy.v1', enabled:true,
40
- lease_file:path.join(root,'autonomous-grant.json'), evidence_dir:path.join(root,'autonomous-evidence'),
47
+ lease_file:path.join(root,'runtime','autonomous-grant.json'), evidence_dir:path.join(root,'autonomous-evidence'),
41
48
  coding_policy_sha256:coding.policy_sha256, root_ids:['project'], planner:{backend:'client_sampling'},
42
49
  limits:{max_iterations:4,max_mutations:4,max_wall_ms:null}, profiles:{} }));
43
50
  const policy = await loadAutonomousPolicy(policyPath, coding);
44
51
  await writeFile(policy.lease_file, JSON.stringify({ schema:'deadbyte.autonomous-grant.v2',
45
52
  policy_sha256:policy.policy_sha256, coding_policy_sha256:coding.policy_sha256,
46
53
  instance_nonce:'b'.repeat(64), root_ids:['project'], granted_at_utc:'2026-09-04T00:00:00Z' }));
54
+ const autonomousBytes=await readFile(policy.lease_file);
55
+ await createAuthorityEpochStore({runtimeDir:path.dirname(policy.lease_file),policyBytes:await readFile(policy.policy_path)}).append({
56
+ plane:'autonomous',action:'grant',grantBytes:autonomousBytes,grantInstanceNonce:'b'.repeat(64),updateId:null
57
+ });
47
58
  const status = await autonomousSessionStatus(policy, farFuture);
48
59
  assert.equal(status.armed, true);
49
60
  assert.equal(status.reason, 'standing-grant');
@@ -55,15 +66,20 @@ test('autonomous standing grant remains armed until explicit revocation', async
55
66
  });
56
67
  test('host standing grant remains armed until explicit revocation', async () => {
57
68
  const root = await mkdtemp(path.join(os.tmpdir(), 'deadbyte-host-standing-'));
69
+ await prepareAuthorityTestTrust(root);
58
70
  const project = path.join(root, 'project');
59
71
  await mkdir(project);
60
72
  const policyPath = path.join(root, 'host.json');
61
73
  await writeFile(policyPath, JSON.stringify({ schema:'deadbyte.host-policy.v1', enabled:true,
62
- arm_file:path.join(root,'host-grant.json'), roots:{ project:{path:project,read:true,write:true,exec:false} },
74
+ arm_file:path.join(root,'runtime','host-grant.json'), roots:{ project:{path:project,read:true,write:true,exec:false} },
63
75
  commands:{} }));
64
76
  const policy = await loadHostPolicy(policyPath);
65
77
  await writeFile(policy.arm_file, JSON.stringify({ schema:'deadbyte.host-grant.v2',
66
78
  policy_sha256:policy.policy_sha256, instance_nonce:'c'.repeat(64), granted_at_utc:'2026-09-04T00:00:00Z' }));
79
+ const hostBytes=await readFile(policy.arm_file);
80
+ await createAuthorityEpochStore({runtimeDir:path.dirname(policy.arm_file),policyBytes:await readFile(policy.policy_path)}).append({
81
+ plane:'host',action:'grant',grantBytes:hostBytes,grantInstanceNonce:'c'.repeat(64),updateId:null
82
+ });
67
83
  const status = await assertHostArmed(policy, farFuture);
68
84
  assert.equal(status.standing, true);
69
85
  assert.equal(status.remaining_ms, null);