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; }> = []; 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 }); } }); });