Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/windows-recovery.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ on:
- 'packages/runtime-host/src/__tests__/skill-catalog-two-client-uds.test.ts'
- 'packages/runtime-host/src/client/client-instance-identity.ts'
- 'packages/runtime-host/src/client/host-profile.ts'
- 'packages/runtime-host/src/client/ssh-operator-activation.ts'
- 'packages/runtime-host/src/client/ssh-tunnel.ts'
- 'packages/runtime-host/src/client/wsl-control.ts'
- 'packages/runtime-host/src/control/access-credential-delivery.ts'
Expand All @@ -83,6 +84,7 @@ on:
- 'packages/runtime-host/src/control/startup-diagnostic.ts'
- 'packages/runtime-host/src/operator/local-deployment-owner.ts'
- 'packages/runtime-host/src/operator/managed-deployment.ts'
- 'packages/runtime-host/src/operator/operator-command.ts'
- 'packages/runtime-host/src/peer-mesh/store.ts'
- 'packages/runtime-host/src/peer-reachability/owner.ts'
- 'packages/runtime-host/src/peer-reachability/publisher.ts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ import {
runtimeHostLocalSetupCommand,
} from '../runtime-host-local-operator.js';

const OPERATOR = {
kind: 'node' as const,
platform: 'posix' as const,
nodePath: '/usr/bin/node',
modulePath: '/tmp/maka/operator.mjs',
};

test('local setup installs one managed service for the Desktop root with Direct peer enabled', () => {
assert.deepEqual(
runtimeHostLocalSetupCommand({
Expand Down Expand Up @@ -90,7 +97,7 @@ test('local setup forwards the exact development archive evidence', async (t) =>
version: '0.2.0-development',
serviceId: 'b'.repeat(64),
deploymentId: '00000000-0000-4000-8000-000000000001',
operatorPath: '/tmp/maka/operator',
operator: OPERATOR,
rootPath: '/tmp/maka/root',
rootId: 'a'.repeat(64),
endpoint: 'ws://127.0.0.1:7443/runtime-host',
Expand Down Expand Up @@ -308,7 +315,7 @@ test('local Peer Mesh join keeps invitations off argv and accepts bounded large
const invitation = JSON.stringify({ secret: 'one-time-mesh-secret' });

const result = await operator.runPeerMesh({
operatorPath: '/tmp/maka/operator',
operator: OPERATOR,
action: 'join',
target: {
serviceId: 'b'.repeat(64),
Expand All @@ -320,6 +327,7 @@ test('local Peer Mesh join keeps invitations off argv and accepts bounded large
});

assert.deepEqual(args, [
OPERATOR.modulePath,
'mesh', 'join', '--framed',
'--expected-service-id', 'b'.repeat(64),
'--expected-root-path', '/tmp/maka/root',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ const RECOVERY_DEPLOYMENT_ID = '33333333-3333-4333-8333-333333333333';
import { createDesktopLocalRuntimeHostRemoteAccess } from '../runtime-host-local-remote-access.js';
import type { createDesktopRuntimeHostLocalOperator } from '../runtime-host-local-operator.js';

const testOperator = (modulePath: string) => ({
kind: 'node' as const,
platform: 'posix' as const,
nodePath: '/usr/bin/node',
modulePath,
});

test('enabling remote access hands the same root to one managed service before Desktop resumes', async (t) => {
const base = await mkdtemp(join(tmpdir(), 'maka-local-remote-access-'));
t.after(() => rm(base, { recursive: true, force: true }));
Expand Down Expand Up @@ -92,7 +99,7 @@ test('enabling remote access hands the same root to one managed service before D
});
return {
serviceId: 'a'.repeat(64),
operatorPath: join(base, 'operator'),
operator: testOperator(join(base, 'operator.mjs')),
rootPath,
rootId: 'a'.repeat(64),
deploymentId,
Expand Down Expand Up @@ -398,11 +405,11 @@ test('replaces a conflicting supervised Host with the requested active-work poli
kind: 'active',
lifecycleMode: 'supervised',
target: {
schemaVersion: 1,
schemaVersion: 2,
serviceId: rootId,
rootPath,
rootId,
operatorPath: join(base, 'operator'),
operator: testOperator(join(base, 'operator.mjs')),
deploymentId: RECOVERY_DEPLOYMENT_ID,
},
}),
Expand Down Expand Up @@ -506,122 +513,121 @@ test('does not persist recoverable setup authority before Desktop ownership comm
assert.equal(setupCalls, 0);
});

test('adopts committed managed authority for every pending receipt without replaying setup', async (t) => {
test('adopts committed managed authority from a released handoff without replaying setup', async (t) => {
const base = await mkdtemp(join(tmpdir(), 'maka-local-remote-access-prestart-'));
t.after(() => rm(base, { recursive: true, force: true }));
for (const state of ['handoff', 'setupPending'] as const) {
const clientDataRoot = join(base, state);
const rootPath = join(clientDataRoot, 'workspaces', 'default');
const rootId = 'a'.repeat(64);
const deploymentId = '22222222-2222-4222-8222-222222222222';
const operatorPath = join(base, 'installed', 'operator');
await mkdir(rootPath, { recursive: true });
await writeFile(
join(clientDataRoot, 'runtime-host-local-service.json'),
`${JSON.stringify({
schemaVersion: 1,
state,
rootPath,
rootId,
coordinationRelays: [],
allowInterruptActiveTasks: true,
})}\n`,
);
const service = createDesktopLocalRuntimeHostRemoteAccess({
ipcMain: { handle() {}, removeHandler() {} },
clientDataRoot,
const clientDataRoot = join(base, 'client');
const rootPath = join(clientDataRoot, 'workspaces', 'default');
const rootId = 'a'.repeat(64);
const deploymentId = '22222222-2222-4222-8222-222222222222';
const installedOperator = testOperator(join(base, 'installed', 'operator.mjs'));
await mkdir(rootPath, { recursive: true });
await writeFile(
join(clientDataRoot, 'runtime-host-local-service.json'),
`${JSON.stringify({
schemaVersion: 1,
state: 'handoff',
rootPath,
rootId,
directPeerAvailable: false,
manager: () => assert.fail('pre-start reconciliation must not require the Local manager'),
resolveManagedDeploymentAuthority: async () => ({
kind: 'active',
lifecycleMode: 'supervised',
target: {
schemaVersion: 1,
serviceId: rootId,
operatorPath,
rootPath,
rootId,
deploymentId,
},
}),
resolveSetupPackage: async () =>
assert.fail('committed authority must not resolve a package'),
operator: {
async runSetup() {
assert.fail('committed authority must not replay setup');
},
async close() {},
} as unknown as ReturnType<typeof createDesktopRuntimeHostLocalOperator>,
});
t.after(() => service.close());

assert.equal(await service.recoverBeforeLocalHostStart(), true);
assert.deepEqual(
JSON.parse(await readFile(join(clientDataRoot, 'runtime-host-local-service.json'), 'utf8')),
{
schemaVersion: 1,
state: 'managed',
coordinationRelays: [],
allowInterruptActiveTasks: true,
})}\n`,
);
const service = createDesktopLocalRuntimeHostRemoteAccess({
ipcMain: { handle() {}, removeHandler() {} },
clientDataRoot,
rootPath,
rootId,
directPeerAvailable: false,
manager: () => assert.fail('pre-start reconciliation must not require the Local manager'),
resolveManagedDeploymentAuthority: async () => ({
kind: 'active',
lifecycleMode: 'supervised',
target: {
schemaVersion: 2,
serviceId: rootId,
operatorPath,
operator: installedOperator,
rootPath,
rootId,
deploymentId,
},
);
}
}),
resolveSetupPackage: async () =>
assert.fail('committed authority must not resolve a package'),
operator: {
async runSetup() {
assert.fail('committed authority must not replay setup');
},
async close() {},
} as unknown as ReturnType<typeof createDesktopRuntimeHostLocalOperator>,
});
t.after(() => service.close());

assert.equal(await service.recoverBeforeLocalHostStart(), true);
assert.deepEqual(
JSON.parse(await readFile(join(clientDataRoot, 'runtime-host-local-service.json'), 'utf8')),
{
schemaVersion: 2,
state: 'managed',
serviceId: rootId,
operator: installedOperator,
rootPath,
rootId,
deploymentId,
},
);
});

test('discards a legacy handoff that belongs to an externally managed Host', async (t) => {
const base = await mkdtemp(join(tmpdir(), 'maka-local-remote-access-legacy-external-'));
test('migrates a released managed receipt before exposing it to lifecycle operations', async (t) => {
const base = await mkdtemp(join(tmpdir(), 'maka-local-managed-migration-'));
t.after(() => rm(base, { recursive: true, force: true }));
const clientDataRoot = join(base, 'client');
const rootPath = join(clientDataRoot, 'workspaces', 'default');
const rootId = 'a'.repeat(64);
const operatorPath = join(base, 'installed', 'operator');
const lifecyclePath = join(clientDataRoot, 'runtime-host-local-service.json');
await mkdir(rootPath, { recursive: true });
await writeFile(
lifecyclePath,
`${JSON.stringify({
schemaVersion: 1,
state: 'handoff',
state: 'managed',
serviceId: rootId,
operatorPath,
rootPath,
rootId,
coordinationRelays: [],
allowInterruptActiveTasks: false,
deploymentId: RECOVERY_DEPLOYMENT_ID,
})}\n`,
);
let setupCalls = 0;
const service = createDesktopLocalRuntimeHostRemoteAccess({
ipcMain: { handle() {}, removeHandler() {} },
clientDataRoot,
rootPath,
rootId,
directPeerAvailable: true,
manager: () =>
({
async retireOwnedLocalHost() {
return { kind: 'not_owned' as const };
},
}) as unknown as RuntimeHostDesktopManager,
resolveManagedDeploymentAuthority: async () => undefined,
manager: () => undefined,
resolveSetupPackage: async () => ({ kind: 'npm', specifier: 'maka-agent@0.2.0' }),
operator: {
async runSetup() {
setupCalls += 1;
throw new Error('setup must not replace an externally managed Host');
},
async close() {},
} as unknown as ReturnType<typeof createDesktopRuntimeHostLocalOperator>,
});
t.after(() => service.close());

assert.equal(await service.recoverBeforeLocalHostStart(), false);
await service.recover();

assert.equal(setupCalls, 0);
await assert.rejects(readFile(lifecyclePath, 'utf8'), { code: 'ENOENT' });
const target = await service.inspectManaged(async (managed) => managed);
const expected = {
schemaVersion: 2,
state: 'managed',
serviceId: rootId,
operator: {
kind: 'legacy_posix_executable',
executablePath: operatorPath,
},
rootPath,
rootId,
deploymentId: RECOVERY_DEPLOYMENT_ID,
};
assert.deepEqual(target, expected);
assert.deepEqual(JSON.parse(await readFile(lifecyclePath, 'utf8')), expected);
});

test('interrupted Local Host setup converges to its exact managed service', async (t) => {
Expand All @@ -634,7 +640,7 @@ test('interrupted Local Host setup converges to its exact managed service', asyn
await writeFile(
join(clientDataRoot, 'runtime-host-local-service.json'),
`${JSON.stringify({
schemaVersion: 1,
schemaVersion: 2,
state: 'setupPending',
rootPath,
rootId,
Expand Down Expand Up @@ -668,7 +674,7 @@ test('interrupted Local Host setup converges to its exact managed service', asyn
setupCalls += 1;
return {
serviceId: rootId,
operatorPath: join(base, 'operator'),
operator: testOperator(join(base, 'operator.mjs')),
rootPath,
rootId,
deploymentId: '22222222-2222-4222-8222-222222222222',
Expand Down Expand Up @@ -708,10 +714,10 @@ test('startup replays the persisted peer intent instead of gating recovery on st
await writeFile(
join(clientDataRoot, 'runtime-host-local-service.json'),
`${JSON.stringify({
schemaVersion: 1,
schemaVersion: 2,
state: 'peerChanging',
serviceId: 'b'.repeat(64),
operatorPath: join(clientDataRoot, 'operator'),
operator: testOperator(join(clientDataRoot, 'operator.mjs')),
rootPath,
rootId,
deploymentId: RECOVERY_DEPLOYMENT_ID,
Expand Down Expand Up @@ -835,10 +841,10 @@ test('pre-start recovery cleans a committed uninstall before an ephemeral Host c
await writeFile(
join(clientDataRoot, 'runtime-host-local-service.json'),
`${JSON.stringify({
schemaVersion: 1,
schemaVersion: 2,
state: 'uninstalling',
serviceId: 'b'.repeat(64),
operatorPath: join(base, 'operator'),
operator: testOperator(join(base, 'operator.mjs')),
rootPath,
rootId,
deploymentId: RECOVERY_DEPLOYMENT_ID,
Expand Down Expand Up @@ -897,10 +903,10 @@ test('pre-start recovery settles a canonical uninstall transition through its ex
await writeFile(
join(clientDataRoot, 'runtime-host-local-service.json'),
`${JSON.stringify({
schemaVersion: 1,
schemaVersion: 2,
state: 'uninstalling',
serviceId: 'b'.repeat(64),
operatorPath: join(base, 'operator'),
operator: testOperator(join(base, 'operator.mjs')),
rootPath,
rootId,
deploymentId: RECOVERY_DEPLOYMENT_ID,
Expand Down Expand Up @@ -955,10 +961,10 @@ async function writeManagedLifecycle(
await writeFile(
join(clientDataRoot, 'runtime-host-local-service.json'),
`${JSON.stringify({
schemaVersion: 1,
schemaVersion: 2,
state: 'managed',
serviceId: 'b'.repeat(64),
operatorPath: join(clientDataRoot, 'operator'),
operator: testOperator(join(clientDataRoot, 'operator.mjs')),
rootPath,
rootId,
deploymentId: RECOVERY_DEPLOYMENT_ID,
Expand Down
Loading
Loading