hivecast-sdk/archive/mx-cli-runtime-host-tests/runner-control-plane.spec.ts

921 lines
34 KiB
TypeScript

import { describe, it } from 'node:test';
import { strict as assert } from 'node:assert';
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import {
InMemoryBroker,
InMemoryTransport,
MatrixActor,
MatrixRuntime,
RequestReply,
subscribeRuntimePresence,
} from '@open-matrix/core';
import { decideMatrixPlacementBind } from '@open-matrix/contracts/placement';
import {
heartbeatRunnerRuntime,
registerRunnerBindings,
registerRunnerRuntime,
shouldRegisterRuntimeInventoryClaim,
} from '../../src/utils/runner-control-plane.js';
import { ServiceRegistryActor } from '@open-matrix/system-platform';
import { BindingsRegistryActor } from '@open-matrix/system-bindings';
import { installRunnerPlacementPolicy } from '../../src/utils/runner-placement-policy.js';
import type { ILoadedMatrixServiceManifest } from '../../src/utils/service-manifest.js';
const runtimePresenceManifest: ILoadedMatrixServiceManifest = {
packageDir: '/tmp/runtime-presence-package',
packageName: '@open-matrix/runtime-presence-test',
packageNamespace: 'runtime-presence-test',
manifestPath: '/tmp/runtime-presence-package/matrix.json',
entryPath: '/tmp/runtime-presence-package/dist/index.js',
exportName: 'RuntimePresenceTestActor',
kind: 'factory',
overrides: {},
root: 'SPACE-RUNNER',
mount: 'runtime-presence-test',
packageRoot: {
mount: 'runtime-presence-test',
accepts: ['runtime-presence.ping'],
},
packageComponents: [],
serviceInstance: {
id: 'runtime-presence-runner',
packageName: '@open-matrix/runtime-presence-test',
class: 'RuntimePresenceTestActor',
rootKind: 'package-root',
autoStart: true,
registrationSource: 'matrix-service',
},
};
class PlacementGatewayActor extends MatrixActor {
static override description = 'Placement gateway test actor';
}
class PlacementCredentialBridgeActor extends MatrixActor {
static override description = 'Placement credential bridge test actor';
}
class FakeAuthorityActor extends MatrixActor {
static override accepts = {
'fake.ping': {},
};
onFakePing(): { ok: true; actor: 'authority' } {
return { ok: true, actor: 'authority' };
}
}
class FakeDeviceActor extends MatrixActor {
static override accepts = {
'fake.ping': {},
};
onFakePing(): { ok: true; actor: 'device' } {
return { ok: true, actor: 'device' };
}
}
describe('runner control plane', () => {
it('keeps ephemeral runtime mounts out of the logical registry', () => {
assert.equal(
shouldRegisterRuntimeInventoryClaim('RUNTIME-HOST-CHAT', 'system.runtimes.RUNTIME-HOST-CHAT'),
false,
);
assert.equal(
shouldRegisterRuntimeInventoryClaim('RUNTIME-HOST-CHAT', 'system.runtimes.RUNTIME-HOST-CHAT.control'),
false,
);
assert.equal(
shouldRegisterRuntimeInventoryClaim('RUNTIME-BROWSER-1234', 'system.runtimes.RUNTIME-BROWSER-1234.director'),
false,
);
});
it('continues to register canonical actor mounts', () => {
assert.equal(shouldRegisterRuntimeInventoryClaim('RUNTIME-HOST-CHAT', 'chat'), true);
assert.equal(shouldRegisterRuntimeInventoryClaim('RUNTIME-HOST-CHAT', 'chat.conversation'), true);
assert.equal(shouldRegisterRuntimeInventoryClaim('RUNTIME-HOST-SYSTEM', 'system.runtimes'), true);
});
it('publishes runtime presence when registering a runner runtime', async () => {
const runtime = new MatrixRuntime({
transport: new InMemoryTransport(new InMemoryBroker(), {
name: 'runner-presence-test',
root: 'SPACE-RUNNER',
}),
logging: false,
});
const observed: string[] = [];
const unsubscribe = subscribeRuntimePresence(
runtime.getRootContext(),
'SPACE-RUNNER',
(record, event) => {
observed.push(`${event}:${record.runtimeId}:${record.app ?? ''}:${record.health?.status ?? ''}`);
},
);
try {
await registerRunnerRuntime(
runtime,
runtimePresenceManifest,
undefined,
undefined,
'runtime-presence-test',
);
// Slice 1b: runtime directory authority is system.runtimes
// (RuntimeManagerActor). registerRunnerRuntime publishes presence on the
// bus; subscribers like RuntimeManagerActor observe and serve it via
// runtimes.list. There is no longer a `kind: 'runtime'` registry claim.
assert.deepEqual(observed, ['announce:runtime-presence-runner:@open-matrix/runtime-presence-test:ok']);
} finally {
unsubscribe();
await runtime.shutdown();
}
});
it('marks linked-device control-plane calls for broker protocol request replies', async () => {
const runtime = new MatrixRuntime({
transport: new InMemoryTransport(new InMemoryBroker(), {
name: 'runner-linked-authority-test',
root: 'test-user-1',
}),
logging: false,
});
try {
const registration = await registerRunnerRuntime(
runtime,
runtimePresenceManifest,
{
packageDir: '/tmp/runtime-presence-package',
envName: 'hivecast',
environmentPath: '/tmp/runtime-presence-package/.matrix/hivecast.environment.json',
environment: {
name: 'hivecast',
runtime: {
root: 'test-user-1',
runtimeId: 'runtime-presence-runner',
},
nats: {
mode: 'external',
url: 'nats://dev-platform:4222',
credentialsRef: 'file:/var/lib/hivecast/credentials/hivecast-nats.json',
},
host: {
matrixDir: '/var/lib/hivecast',
},
},
},
{
envName: 'hivecast',
root: 'test-user-1',
mode: 'external',
url: 'nats://dev-platform:4222',
credentialsRef: 'file:/var/lib/hivecast/credentials/hivecast-nats.json',
},
'runtime-presence-test',
);
assert.equal(registration.controlTargetRoot, 'test-user-1');
assert.equal(registration.protocolRequest, true);
} finally {
await runtime.shutdown();
}
});
it('reclaim re-issues registry.claim after the registry actor was wiped (simulates SYSTEM restart)', async () => {
// This test pins the production failure mode that motivated the reclaim()
// closure on IRunnerRuntimeRegistration / IRunnerBindingRegistration:
//
// 1. Runner registers, registry stores claim in its in-memory _claims Map
// 2. SYSTEM runtime restarts (deploy, supervisor bounce). Its _claims
// starts empty
// 3. Runner's 10s heartbeat calls registry.claim.renew → registry has
// no record → returns { renewed: 0 }
// 4. Without reclaim, the runner's original 45s-TTL claim expires and
// the runtime vanishes from registry.query
//
// The fix: heartbeatRunnerRuntime / renewRunnerBindings return
// { known: false } / { refreshed: 0 } when the registry forgot us, and
// the heartbeat tick calls registration.reclaim() to re-issue claims.
const home = mkdtempSync(join(tmpdir(), 'runner-reclaim-test-'));
writeFileSync(join(home, 'matrix.json'), JSON.stringify({
name: '@open-matrix/reclaim-test',
root: {
type: 'ReclaimTestRootActor',
mount: 'reclaim-test',
},
components: [],
}));
const reclaimManifest: ILoadedMatrixServiceManifest = {
...runtimePresenceManifest,
packageDir: home,
packageName: '@open-matrix/reclaim-test',
packageNamespace: 'reclaim-test',
manifestPath: join(home, 'matrix.json'),
entryPath: join(home, 'dist/index.js'),
packageRoot: {
mount: 'reclaim-test',
accepts: ['reclaim.ping'],
},
serviceInstance: {
...runtimePresenceManifest.serviceInstance,
id: 'reclaim-test-runner',
packageName: '@open-matrix/reclaim-test',
},
};
const runtime = new MatrixRuntime({
transport: new InMemoryTransport(new InMemoryBroker(), {
name: 'runner-reclaim-test',
root: 'SPACE-RECLAIM',
}),
logging: false,
});
const queryRegistry = async () => await RequestReply.execute(
runtime.getRootContext(),
'system.registry',
'registry.query',
{ kind: 'actor', includeStale: true },
{ timeoutMs: 5_000 },
) as { entries?: Array<{ mount?: string; providerRuntimeId?: string }> };
const queryBindings = async () => await RequestReply.execute(
runtime.getRootContext(),
'system.bindings',
'bindings.list',
{},
{ timeoutMs: 5_000 },
) as { ok?: boolean; count?: number; bindings?: Array<{ binding?: string }> };
try {
const runtimeRegistration = await registerRunnerRuntime(
runtime,
reclaimManifest,
undefined,
undefined,
'reclaim-test',
);
const bindingRegistration = await registerRunnerBindings(
runtime,
reclaimManifest,
undefined,
runtimeRegistration.runtimeId,
'reclaim-test',
);
// Sanity: both registries know about us before wipe.
const beforeWipeRegistry = await queryRegistry();
const beforeRegistryMounts = new Set((beforeWipeRegistry.entries ?? []).map((e) => e.mount));
assert.ok(beforeRegistryMounts.size > 0, 'system.registry should have at least one claim before wipe');
const beforeWipeBindings = await queryBindings();
const beforeBindingMounts = new Set((beforeWipeBindings.bindings ?? []).map((b) => b.binding));
assert.ok(beforeBindingMounts.size > 0, 'system.bindings should have at least one binding before wipe');
// Simulate SYSTEM restart: tear down BOTH registries and replace them
// with fresh ones. Their _claims / _bindings maps start empty —
// exactly the state the production registries are in right after a
// SYSTEM bounce.
await runtime.remove('system.registry');
await runtime.remove('system.bindings');
await runtime.createSupervised(ServiceRegistryActor, 'system.registry');
await runtime.createSupervised(BindingsRegistryActor, 'system.bindings');
const afterWipeRegistry = await queryRegistry();
assert.deepEqual(
afterWipeRegistry.entries ?? [],
[],
'system.registry should be empty after wipe (production failure mode)',
);
const afterWipeBindings = await queryBindings();
assert.deepEqual(
afterWipeBindings.bindings ?? [],
[],
'system.bindings should be empty after wipe (production failure mode)',
);
// Reclaim should restore every server-side record we published at
// registration time. After both calls the registries see us again.
const runtimeReclaim = await runtimeRegistration.reclaim();
assert.ok(
runtimeReclaim.inventoryClaimCount >= 0,
'runtime reclaim returns the count of inventory claims re-issued',
);
const bindingReclaim = await bindingRegistration.reclaim();
assert.ok(
bindingReclaim.registryClaimCount >= 1,
'binding reclaim re-issues at least the canonical package-root registry claim',
);
assert.ok(
bindingReclaim.bindingsRegisteredCount >= 1,
'binding reclaim re-issues at least the canonical package-root bindings.register',
);
assert.equal(
bindingReclaim.registryClaimCount,
bindingReclaim.bindingsRegisteredCount,
'every canonical binding produces exactly one registry.claim AND one bindings.register; reclaim must restore them in lockstep',
);
const afterReclaimRegistry = await queryRegistry();
const afterReclaimRegistryMounts = new Set((afterReclaimRegistry.entries ?? []).map((e) => e.mount));
assert.ok(
afterReclaimRegistryMounts.size >= beforeRegistryMounts.size,
`reclaim should restore all registry claims (had ${beforeRegistryMounts.size}, now ${afterReclaimRegistryMounts.size})`,
);
assert.ok(
afterReclaimRegistryMounts.has('reclaim-test'),
'canonical package-root registry claim should be reclaimed',
);
const afterReclaimBindings = await queryBindings();
const afterReclaimBindingMounts = new Set((afterReclaimBindings.bindings ?? []).map((b) => b.binding));
assert.deepEqual(
afterReclaimBindingMounts,
beforeBindingMounts,
'reclaim should restore every bindings.register record (otherwise canonical lookups break silently)',
);
} finally {
await runtime.shutdown();
rmSync(home, { recursive: true, force: true });
}
});
it('publishes placement metadata for runtime inventory and registry claims', async () => {
const home = mkdtempSync(join(tmpdir(), 'runner-placement-manifest-'));
const manifestPath = join(home, 'matrix.json');
writeFileSync(manifestPath, JSON.stringify({
name: '@open-matrix/placement-test',
root: {
type: 'PlacementRootActor',
mount: 'system',
},
components: [
{
type: 'PlacementRegistryActor',
mount: 'system.registry',
placement: { cardinality: 'authority-singleton' },
},
{
type: 'PlacementGatewayActor',
mount: 'system.gateway',
placement: { cardinality: 'device-local-control' },
},
{
type: 'PlacementCredentialBridgeActor',
mount: 'system.security.credential-bridge',
placement: { cardinality: 'device-singleton' },
},
],
}));
const manifest: ILoadedMatrixServiceManifest = {
...runtimePresenceManifest,
packageDir: home,
packageName: '@open-matrix/placement-test',
packageNamespace: 'system',
manifestPath,
entryPath: join(home, 'dist/index.js'),
serviceInstance: {
...runtimePresenceManifest.serviceInstance,
id: 'placement-test-runner',
packageName: '@open-matrix/placement-test',
},
};
const runtime = new MatrixRuntime({
transport: new InMemoryTransport(new InMemoryBroker(), {
name: 'runner-placement-test',
root: 'SPACE-RUNNER',
}),
logging: false,
});
try {
await runtime.createSupervised(PlacementGatewayActor, 'system.gateway');
await runtime.createSupervised(PlacementCredentialBridgeActor, 'system.security.credential-bridge');
const registration = await registerRunnerRuntime(
runtime,
manifest,
undefined,
undefined,
'system',
);
const inventoryByMount = new Map(
(registration.presence.inventory ?? []).map((entry) => [entry.mount, entry]),
);
assert.equal(inventoryByMount.get('system.registry')?.placement?.cardinality, 'authority-singleton');
assert.equal(inventoryByMount.get('system.registry')?.placement?.claimMode, 'authoritative');
assert.equal(inventoryByMount.get('system.registry')?.placement?.logicalMount, 'system.registry');
assert.equal(inventoryByMount.get('system.registry')?.placement?.physicalMount, 'system.registry');
assert.equal(inventoryByMount.get('system.registry')?.placement?.callable, true);
assert.equal(inventoryByMount.get('system.gateway')?.placement?.cardinality, 'device-local-control');
assert.equal(inventoryByMount.get('system.gateway')?.placement?.claimMode, 'local-only');
assert.equal(inventoryByMount.get('system.security.credential-bridge')?.placement?.cardinality, 'device-singleton');
assert.equal(inventoryByMount.get('system.security.credential-bridge')?.placement?.claimMode, 'local-only');
const actorEntries = await RequestReply.execute(
runtime.getRootContext(),
'system.registry',
'registry.query',
{ namespaceRoot: 'SPACE-RUNNER', kind: 'actor' },
{ timeoutMs: 5_000 },
) as {
entries?: Array<{
mount?: string;
claim?: { mode?: string };
placement?: {
cardinality?: string;
claimMode?: string;
logicalMount?: string;
physicalMount?: string;
callable?: boolean;
};
metadata?: { placement?: { callable?: boolean } };
}>;
};
const byMount = new Map((actorEntries.entries ?? []).map((entry) => [entry.mount, entry]));
assert.equal(byMount.get('system.registry')?.claim?.mode, 'authoritative');
assert.equal(byMount.get('system.registry')?.placement?.cardinality, 'authority-singleton');
assert.equal(byMount.get('system.registry')?.placement?.claimMode, 'authoritative');
assert.equal(byMount.get('system.registry')?.placement?.callable, true);
assert.equal(byMount.get('system.registry')?.metadata?.placement?.callable, true);
assert.equal(byMount.get('system.gateway')?.claim?.mode, 'local-only');
assert.equal(byMount.get('system.gateway')?.placement?.cardinality, 'device-local-control');
assert.equal(byMount.get('system.gateway')?.placement?.callable, true);
assert.equal(byMount.get('system.security.credential-bridge')?.claim?.mode, 'local-only');
assert.equal(byMount.get('system.security.credential-bridge')?.placement?.cardinality, 'device-singleton');
} finally {
await runtime.shutdown();
rmSync(home, { recursive: true, force: true });
}
});
it('blocks manifest authority-singleton actors before inbox bind on standby topology', async () => {
const home = mkdtempSync(join(tmpdir(), 'runner-placement-denial-'));
writeFileSync(join(home, 'matrix.json'), JSON.stringify({
name: '@open-matrix/placement-denial-test',
components: [
{
type: 'FakeAuthorityActor',
mount: 'system.fakeAuthority',
placement: {
cardinality: 'authority-singleton',
},
},
{
type: 'FakeDeviceActor',
mount: 'system.fakeDevice',
placement: {
cardinality: 'device-local-control',
},
},
],
}));
const manifest: ILoadedMatrixServiceManifest = {
...runtimePresenceManifest,
packageDir: home,
packageName: '@open-matrix/placement-denial-test',
packageNamespace: 'system',
manifestPath: join(home, 'matrix.json'),
entryPath: join(home, 'dist/index.js'),
packageComponents: [
{
mount: 'system.fakeAuthority',
accepts: ['fake.ping'],
},
{
mount: 'system.fakeDevice',
accepts: ['fake.ping'],
},
],
serviceInstance: {
...runtimePresenceManifest.serviceInstance,
id: 'placement-denial-runner',
packageName: '@open-matrix/placement-denial-test',
},
};
const runtime = new MatrixRuntime({
transport: new InMemoryTransport(new InMemoryBroker(), {
name: 'runner-placement-denial-test',
root: 'SPACE-HIVECAST-LAB',
}),
logging: false,
});
try {
installRunnerPlacementPolicy({
runtime,
manifest,
environment: {
packageDir: home,
envName: 'standby',
environmentPath: join(home, '.matrix', 'standby.environment.json'),
environment: {
name: 'standby',
runtime: {
root: 'SPACE-HIVECAST-LAB',
runtimeId: 'placement-denial-runner',
},
topology: {
kind: 'linked-device',
roles: {
authorityCoordinator: {
active: false,
reason: 'linked-device-standby',
},
},
authority: {
authorityRoot: 'SPACE-HIVECAST-LAB',
},
},
},
},
runtimeId: 'placement-denial-runner',
authorityRoot: 'SPACE-HIVECAST-LAB',
});
await assert.rejects(
() => runtime.createSupervised(FakeAuthorityActor, 'system.fakeAuthority'),
/SINGLETON_MOUNT_NOT_OWNED/,
);
await runtime.createSupervised(FakeDeviceActor, 'system.fakeDevice');
const registration = await registerRunnerRuntime(
runtime,
manifest,
undefined,
undefined,
'system',
);
const bindings = await registerRunnerBindings(
runtime,
manifest,
undefined,
registration.runtimeId,
'system',
);
assert.equal(runtime.hasComponent('system.fakeAuthority'), false);
assert.equal(runtime.hasComponent('system.fakeDevice'), true);
assert.equal(bindings.bindings.some((binding) => binding.localMount === 'system.fakeAuthority'), false);
assert.equal(bindings.bindings.some((binding) => binding.localMount === 'system.fakeDevice'), true);
await assert.rejects(
() => RequestReply.execute(
runtime.getRootContext(),
'system.fakeAuthority',
'fake.ping',
{},
{ timeoutMs: 150 },
),
);
const deviceReply = await RequestReply.execute(
runtime.getRootContext(),
'system.fakeDevice',
'fake.ping',
{},
{ timeoutMs: 5_000 },
) as { ok?: boolean; actor?: string };
assert.deepEqual(deviceReply, { ok: true, actor: 'device' });
const inventoryByMount = new Map(
(registration.presence.inventory ?? []).map((entry) => [entry.mount, entry]),
);
assert.equal(inventoryByMount.get('system.fakeAuthority')?.placement?.cardinality, 'authority-singleton');
assert.equal(inventoryByMount.get('system.fakeAuthority')?.placement?.callable, false);
assert.equal(
inventoryByMount.get('system.fakeAuthority')?.placement?.standbyReason,
'SINGLETON_MOUNT_NOT_OWNED',
);
assert.equal(inventoryByMount.get('system.fakeDevice')?.placement?.cardinality, 'device-local-control');
assert.equal(inventoryByMount.get('system.fakeDevice')?.placement?.claimMode, 'local-only');
assert.equal(inventoryByMount.get('system.fakeDevice')?.placement?.callable, true);
// Slice 1b: query without namespaceRoot filter because
// registerRuntimeInventoryClaims writes claims with manifest.root as the
// namespaceRoot, while presence uses the transport root. The substrate
// truth here is "system.fakeDevice is claimed by this runtime" — the
// test does not need to assert which namespaceRoot the claim is stored
// under (that's a separate pre-existing inconsistency the workstream
// does not address).
const actorEntries = await RequestReply.execute(
runtime.getRootContext(),
'system.registry',
'registry.query',
{ kind: 'actor', includeStale: true },
{ timeoutMs: 5_000 },
) as {
entries?: Array<{
mount?: string;
placement?: {
cardinality?: string;
claimMode?: string;
callable?: boolean;
};
}>;
};
const byMount = new Map((actorEntries.entries ?? []).map((entry) => [entry.mount, entry]));
assert.equal(byMount.has('system.fakeAuthority'), false);
assert.equal(byMount.get('system.fakeDevice')?.placement?.cardinality, 'device-local-control');
assert.equal(byMount.get('system.fakeDevice')?.placement?.claimMode, 'local-only');
assert.equal(byMount.get('system.fakeDevice')?.placement?.callable, true);
} finally {
await runtime.shutdown();
rmSync(home, { recursive: true, force: true });
}
});
it('uses authority leases to fence active authority-singleton placement', () => {
const activeLease = {
version: 1 as const,
authorityRoot: 'SPACE-HIVECAST-LAB',
leaseId: 'lease-active',
ownerNodeId: 'owner-a',
placementEpoch: 2,
acquiredAt: '2026-05-09T00:00:00.000Z',
heartbeatAt: '2026-05-09T00:00:00.000Z',
expiresAt: '2026-05-09T00:05:00.000Z',
status: 'active' as const,
scope: 'local-home' as const,
leaseAuthority: 'local' as const,
source: 'local-file' as const,
};
assert.equal(decideMatrixPlacementBind({
authorityRoot: 'SPACE-HIVECAST-LAB',
mount: 'system.registry',
cardinality: 'authority-singleton',
authorityCoordinatorActive: true,
ownerNodeId: 'owner-a',
authorityLease: activeLease,
}).allowed, true);
const nonOwned = decideMatrixPlacementBind({
authorityRoot: 'SPACE-HIVECAST-LAB',
mount: 'system.registry',
cardinality: 'authority-singleton',
authorityCoordinatorActive: true,
ownerNodeId: 'owner-b',
authorityLease: activeLease,
});
assert.equal(nonOwned.allowed, false);
assert.equal(nonOwned.reason, 'AUTHORITY_COORDINATOR_LEASE_NOT_OWNED');
const fenced = decideMatrixPlacementBind({
authorityRoot: 'SPACE-HIVECAST-LAB',
mount: 'system.registry',
cardinality: 'authority-singleton',
authorityCoordinatorActive: true,
ownerNodeId: 'owner-a',
authorityLease: {
...activeLease,
status: 'fenced',
reason: 'LEASE_FORCED',
},
});
assert.equal(fenced.allowed, false);
assert.equal(fenced.reason, 'AUTHORITY_COORDINATOR_LEASE_NOT_OWNED');
assert.equal(decideMatrixPlacementBind({
authorityRoot: 'SPACE-HIVECAST-LAB',
mount: 'system.registry',
cardinality: 'authority-singleton',
authorityCoordinatorActive: true,
ownerNodeId: 'owner-a',
}).allowed, true);
});
it('claims webapp surfaces in system.registry for shell launchers', async () => {
const runtime = new MatrixRuntime({
transport: new InMemoryTransport(new InMemoryBroker(), {
name: 'runner-webapp-surface-test',
root: 'SPACE-RUNNER',
}),
logging: false,
});
try {
const registration = await registerRunnerRuntime(
runtime,
runtimePresenceManifest,
undefined,
undefined,
'runtime-presence-test',
undefined,
undefined,
{
appName: 'director',
routePrefix: '/apps/director/',
displayName: 'Director',
icon: 'director',
navOrder: 20,
description: 'Matrix actor hierarchy explorer',
shells: ['platform', 'edge'],
assetMount: 'system.runtimes.runtime-presence-runner.http',
},
);
const appEntries = await RequestReply.execute(
runtime.getRootContext(),
'system.registry',
'registry.query',
{ namespaceRoot: 'SPACE-RUNNER', kind: 'app', openable: true },
{ timeoutMs: 5_000 },
) as {
entries?: Array<{
mount?: string;
app?: { appName?: string; route?: string; title?: string; icon?: string; openable?: boolean };
metadata?: { source?: string; assetMount?: string; routeKind?: string; description?: string; navOrder?: number; shells?: string[] };
placement?: { runtimeId?: string; packageRef?: string };
}>;
};
assert.ok(registration.inventoryClaimCount >= 1);
assert.deepEqual(appEntries.entries?.map((entry) => entry.mount), ['director']);
assert.equal(appEntries.entries?.[0]?.app?.appName, 'director');
assert.equal(appEntries.entries?.[0]?.app?.title, 'Director');
assert.equal(appEntries.entries?.[0]?.app?.icon, 'director');
assert.equal(appEntries.entries?.[0]?.app?.route, '/apps/director/');
assert.equal(appEntries.entries?.[0]?.app?.openable, true);
assert.equal(appEntries.entries?.[0]?.metadata?.source, 'runner-webapp-surface');
assert.equal(appEntries.entries?.[0]?.metadata?.description, 'Matrix actor hierarchy explorer');
assert.equal(appEntries.entries?.[0]?.metadata?.navOrder, 20);
assert.deepEqual(appEntries.entries?.[0]?.metadata?.shells, ['platform', 'edge']);
assert.equal(appEntries.entries?.[0]?.metadata?.routeKind, 'matrix-asset-endpoint');
assert.equal(appEntries.entries?.[0]?.metadata?.assetMount, 'system.runtimes.runtime-presence-runner.http');
assert.equal(appEntries.entries?.[0]?.placement?.runtimeId, 'runtime-presence-runner');
assert.equal(appEntries.entries?.[0]?.placement?.packageRef, '@open-matrix/runtime-presence-test');
await runtime.remove('system.registry');
await runtime.createSupervised(ServiceRegistryActor, 'system.registry');
const afterWipe = await RequestReply.execute(
runtime.getRootContext(),
'system.registry',
'registry.query',
{ namespaceRoot: 'SPACE-RUNNER', kind: 'app', openable: true },
{ timeoutMs: 5_000 },
) as { entries?: Array<{ mount?: string }> };
assert.deepEqual(afterWipe.entries ?? [], []);
const heartbeat = await heartbeatRunnerRuntime(runtime, registration);
assert.equal(heartbeat?.known, false);
const reclaimed = await registration.reclaim();
assert.ok(
reclaimed.inventoryClaimCount >= 1,
'webapp runtime reclaim re-issues the app-surface registry claim after a SYSTEM restart',
);
const reclaimedAppEntries = await RequestReply.execute(
runtime.getRootContext(),
'system.registry',
'registry.query',
{ namespaceRoot: 'SPACE-RUNNER', kind: 'app', openable: true },
{ timeoutMs: 5_000 },
) as { entries?: Array<{ mount?: string; metadata?: { source?: string } }> };
assert.deepEqual(reclaimedAppEntries.entries?.map((entry) => entry.mount), ['director']);
assert.equal(reclaimedAppEntries.entries?.[0]?.metadata?.source, 'runner-webapp-surface');
} finally {
await runtime.shutdown();
}
});
it('projects Host identity into Service Registry placement', async () => {
const home = mkdtempSync(join(tmpdir(), 'runner-host-placement-'));
mkdirSync(join(home, 'credentials'), { recursive: true });
writeFileSync(join(home, 'credentials', 'hivecast-install.json'), JSON.stringify({
version: 1,
installId: 'install_test000000000003',
hostName: 'Test Device',
}));
writeFileSync(join(home, 'credentials', 'hivecast-link.json'), JSON.stringify({
version: 1,
hostId: 'install_test000000000003',
hostName: 'Test Device',
deviceSlug: 'test-device',
}));
const runtime = new MatrixRuntime({
transport: new InMemoryTransport(new InMemoryBroker(), {
name: 'runner-host-placement-test',
root: 'SPACE-RUNNER',
}),
logging: false,
});
runtime.registerService('matrix-host-home', home);
const observed: Array<{
runtimeId: string;
metadata?: Record<string, unknown>;
}> = [];
const unsubscribe = subscribeRuntimePresence(
runtime.getRootContext(),
'SPACE-RUNNER',
(record) => {
observed.push({
runtimeId: record.runtimeId,
...(record.metadata ? { metadata: record.metadata } : {}),
});
},
);
try {
await registerRunnerRuntime(
runtime,
runtimePresenceManifest,
undefined,
undefined,
'runtime-presence-test',
undefined,
undefined,
{
appName: 'director',
routePrefix: '/apps/director/',
assetMount: 'system.runtimes.runtime-presence-runner.http',
},
);
const appEntries = await RequestReply.execute(
runtime.getRootContext(),
'system.registry',
'registry.query',
{ namespaceRoot: 'SPACE-RUNNER', kind: 'app', openable: true },
{ timeoutMs: 5_000 },
) as {
entries?: Array<{
placement?: { deviceId?: string; hostId?: string };
metadata?: { deviceId?: string; hostId?: string; hostName?: string; deviceSlug?: string };
}>;
};
// Slice 1b: real registry app claim still carries Host identity.
assert.equal(appEntries.entries?.[0]?.placement?.deviceId, 'install_test000000000003');
assert.equal(appEntries.entries?.[0]?.placement?.hostId, 'install_test000000000003');
assert.equal(appEntries.entries?.[0]?.metadata?.hostName, 'Test Device');
assert.equal(appEntries.entries?.[0]?.metadata?.deviceSlug, 'test-device');
// Runtime identity in this test is now asserted via presence (the
// runtime directory authority), not via a registry kind=runtime claim.
assert.equal(observed[0]?.metadata?.deviceId, 'install_test000000000003');
assert.equal(observed[0]?.metadata?.hostName, 'Test Device');
} finally {
unsubscribe();
await runtime.shutdown();
rmSync(home, { recursive: true, force: true });
}
});
it('does not require Host placement before a fresh local install has identity files', async () => {
const home = mkdtempSync(join(tmpdir(), 'runner-host-placement-empty-'));
mkdirSync(join(home, 'credentials'), { recursive: true });
const runtime = new MatrixRuntime({
transport: new InMemoryTransport(new InMemoryBroker(), {
name: 'runner-host-placement-empty-test',
root: 'SPACE-RUNNER',
}),
logging: false,
});
runtime.registerService('matrix-host-home', home);
try {
await registerRunnerRuntime(
runtime,
runtimePresenceManifest,
undefined,
undefined,
'runtime-presence-test',
undefined,
undefined,
{
appName: 'director',
routePrefix: '/apps/director/',
assetMount: 'system.runtimes.runtime-presence-runner.http',
},
);
const appEntries = await RequestReply.execute(
runtime.getRootContext(),
'system.registry',
'registry.query',
{ namespaceRoot: 'SPACE-RUNNER', kind: 'app', openable: true },
{ timeoutMs: 5_000 },
) as {
entries?: Array<{
placement?: { deviceId?: string; hostId?: string };
metadata?: { deviceId?: string; hostId?: string };
}>;
};
assert.equal(appEntries.entries?.[0]?.placement?.deviceId, undefined);
assert.equal(appEntries.entries?.[0]?.placement?.hostId, undefined);
assert.equal(appEntries.entries?.[0]?.metadata?.deviceId, undefined);
assert.equal(appEntries.entries?.[0]?.metadata?.hostId, undefined);
} finally {
await runtime.shutdown();
rmSync(home, { recursive: true, force: true });
}
});
});