| import assert from 'node:assert/strict'; |
| import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; |
| import { tmpdir } from 'node:os'; |
| import { join } from 'node:path'; |
| import test from 'node:test'; |
| import { |
| collectRuntimeHostFailureDiagnostic, |
| retireCollectedRuntimeHostStartupDiagnostic, |
| } from './release-cli-runtime-host-diagnostics.mjs'; |
| |
| const ROOT_ID = 'a'.repeat(64); |
| const STARTUP_ATTEMPT_ID = '00000000-0000-4000-8000-000000000001'; |
| |
| test('collects canonical Runtime Host evidence without invoking mutating storage authority', async () => { |
| const fixture = createFixture(); |
| try { |
| const startupDiagnostic = { |
| schemaVersion: 1, |
| rootId: ROOT_ID, |
| startupAttemptId: STARTUP_ATTEMPT_ID, |
| candidatePid: 123, |
| capturedAt: '2026-08-19T00:00:00.000Z', |
| reason: 'local_ipc_security_failed', |
| errorChain: [{ message: '{"stage":"acl_apply"}' }], |
| logs: ['endpoint setup failed'], |
| }; |
| const securityCalls = []; |
| const diagnostic = await collectRuntimeHostFailureDiagnostic('/installed', fixture.root, { |
| platform: 'win32', |
| architecture: 'x64', |
| environment: { |
| ImageOS: 'win25', |
| ImageVersion: '20260817.1', |
| RUNNER_NAME: 'hosted-runner', |
| RUNNER_ENVIRONMENT: 'github-hosted', |
| }, |
| loadInstalled: async (_packageRoot, relativePath) => { |
| if (relativePath.endsWith('/root-authority.js')) { |
| return { |
| STORAGE_ROOT_MARKER_FILE: '.maka-storage-root.json', |
| discoverMarkedStorageRoot: async () => ({ rootId: ROOT_ID }), |
| resolveRootControlNamespace: () => fixture.controlRoot, |
| }; |
| } |
| if (relativePath.endsWith('/registration.js')) { |
| return { |
| RUNTIME_HOST_REGISTRATION_FILE: 'registration.json', |
| readHostRegistration: async () => ({ |
| schemaVersion: 1, |
| rootId: ROOT_ID, |
| hostEpoch: 'host-epoch', |
| state: 'recovering', |
| lifecycleMode: 'interactive', |
| pid: 123, |
| endpoint: '\\\\.\\pipe\\maka-runtime-host', |
| }), |
| }; |
| } |
| if (relativePath.endsWith('/startup-diagnostic.js')) { |
| return { |
| RUNTIME_HOST_STARTUP_DIAGNOSTIC_FILE: 'startup-diagnostic.json', |
| readCandidateStartupDiagnostic: async () => startupDiagnostic, |
| }; |
| } |
| throw new Error(`Unexpected installed module: ${relativePath}`); |
| }, |
| readPathSecurityBatch: async (paths) => { |
| securityCalls.push(paths); |
| return paths.map(() => ({ |
| state: 'present', |
| owner: 'runner\\user', |
| sddl: 'O:SYD:P', |
| })); |
| }, |
| }); |
| |
| assert.deepEqual( |
| diagnostic.paths.map(({ role }) => role), |
| [ |
| 'root', |
| 'root_marker', |
| 'control_root', |
| 'control_directory', |
| 'registration', |
| 'startup_diagnostic', |
| ], |
| ); |
| assert.deepEqual(securityCalls, [ |
| [fixture.root, fixture.controlRoot, fixture.controlDirectory], |
| ]); |
| assert.equal(diagnostic.paths[0].security.owner, 'runner\\user'); |
| assert.equal(diagnostic.storageAuthority.state, 'valid'); |
| assert.equal(diagnostic.registration.rootIdMatches, true); |
| assert.deepEqual(diagnostic.startup, { state: 'present', diagnostic: startupDiagnostic }); |
| assert.equal(diagnostic.runner.architecture, undefined); |
| |
| let retired; |
| assert.equal( |
| await retireCollectedRuntimeHostStartupDiagnostic('/installed', diagnostic, { |
| loadInstalled: async (_packageRoot, relativePath) => { |
| assert.match(relativePath, /startup-diagnostic\.js$/u); |
| return { |
| clearSelectedCandidateStartupDiagnostic: async (rootId, startupAttemptId) => { |
| retired = { rootId, startupAttemptId }; |
| return true; |
| }, |
| }; |
| }, |
| }), |
| true, |
| ); |
| assert.deepEqual(retired, { rootId: ROOT_ID, startupAttemptId: STARTUP_ATTEMPT_ID }); |
| } finally { |
| fixture.cleanup(); |
| } |
| }); |
| |
| test('keeps read-only path evidence when root authority validation fails', async () => { |
| const fixture = createFixture({ createControlDirectory: false }); |
| try { |
| const diagnostic = await collectRuntimeHostFailureDiagnostic('/installed', fixture.root, { |
| platform: 'win32', |
| loadInstalled: async (_packageRoot, relativePath) => { |
| if (!relativePath.endsWith('/root-authority.js')) { |
| throw new Error(`Unexpected installed module: ${relativePath}`); |
| } |
| return { |
| STORAGE_ROOT_MARKER_FILE: '.maka-storage-root.json', |
| discoverMarkedStorageRoot: async () => { |
| throw new Error('marker validation failed', { |
| cause: Object.assign(new Error('Access is denied'), { code: 'EACCES' }), |
| }); |
| }, |
| resolveRootControlNamespace: () => fixture.controlRoot, |
| }; |
| }, |
| readPathSecurityBatch: async (paths) => { |
| return paths.map((path) => |
| path === fixture.root |
| ? { |
| state: 'unavailable', |
| error: { name: 'UnauthorizedAccessException', nativeErrorCode: 5 }, |
| } |
| : { state: 'present', owner: 'runner\\user', sddl: 'O:SYD:P' }, |
| ); |
| }, |
| }); |
| |
| assert.equal(diagnostic.storageAuthority.state, 'invalid'); |
| assert.equal(diagnostic.storageAuthority.error.cause.code, 'EACCES'); |
| assert.equal(diagnostic.paths[0].security.state, 'unavailable'); |
| assert.equal(diagnostic.paths[0].security.error.nativeErrorCode, 5); |
| assert.deepEqual( |
| diagnostic.paths.map(({ role }) => role), |
| ['root', 'root_marker', 'control_root'], |
| ); |
| assert.equal(existsSync(fixture.controlDirectory), false); |
| } finally { |
| fixture.cleanup(); |
| } |
| }); |
| |
| function createFixture({ createControlDirectory = true } = {}) { |
| const base = mkdtempSync(join(tmpdir(), 'maka-runtime-host-diagnostic-test-')); |
| const root = join(base, 'root'); |
| const controlRoot = join(base, 'control'); |
| const controlDirectory = join(controlRoot, ROOT_ID); |
| const registrationPath = join(controlDirectory, 'registration.json'); |
| const startupPath = join(controlDirectory, 'startup-diagnostic.json'); |
| mkdirSync(root, { recursive: true }); |
| mkdirSync(controlRoot, { recursive: true }); |
| writeFileSync(join(root, '.maka-storage-root.json'), '{}\n'); |
| if (createControlDirectory) { |
| mkdirSync(controlDirectory, { recursive: true }); |
| writeFileSync(registrationPath, '{}\n'); |
| writeFileSync(startupPath, '{}\n'); |
| } |
| return { |
| root, |
| controlRoot, |
| controlDirectory, |
| registrationPath, |
| startupPath, |
| cleanup: () => rmSync(base, { recursive: true, force: true }), |
| }; |
| } |