hivecast-sdk/packages/federation/tests/integration/cross-realm-two-gateways.spec.ts

274 lines
7.7 KiB
TypeScript
Raw Normal View History

/**
* Cross-Realm Two-Gateway Integration Test
*
* Tests actual cross-realm communication where:
* - Realm A's EdgeGateway sends a message
* - Backbone routes it to Realm B's mailbox
* - Realm B's EdgeGateway receives and processes it
* - Reply flows back to Realm A
*/
import { describe, it } from 'node:test';
import { strict as assert } from 'node:assert';
import {
FederationPeer, ExactInstanceResolver,
WIRE_PROFILES,
InMemoryFilterBroker,
getLegacyIngressTopic,
createLegacyRequest,
serializeLegacyEnvelope,
} from '@open-matrix/federation';
describe('Cross-Realm Two Gateways', () => {
it('Realm A sends request to Realm B and receives reply', async () => {
const REALM_A = 'realm-alpha';
const REALM_B = 'realm-beta';
// Shared backbone broker (simulates HiveMQ)
const backbone = new InMemoryFilterBroker();
// Realm A's local bus
const localBusA = new InMemoryFilterBroker();
// Realm B's local bus
const localBusB = new InMemoryFilterBroker();
// Create EdgeGateway for Realm A
const gatewayA = new FederationPeer({
localRealm: REALM_A,
profile: WIRE_PROFILES.matrix3,
backbone,
localBus: localBusA,
internalTimeoutMs: 5000,
});
// Create EdgeGateway for Realm B
const gatewayB = new FederationPeer({
localRealm: REALM_B,
profile: WIRE_PROFILES.matrix3,
backbone,
localBus: localBusB,
internalTimeoutMs: 5000,
});
// Start both gateways
gatewayA.start();
gatewayB.start();
// Set up handler on Realm B's local bus
localBusB.subscribe(`calculator.accepts.add`, (topic, payload) => {
const req = JSON.parse(payload) as {
replyTo: string;
correlationId: string;
params: { a: number; b: number };
};
// Calculate result
const result = req.params.a + req.params.b;
// Send reply
localBusB.publish(req.replyTo, JSON.stringify({
ok: true,
correlationId: req.correlationId,
result: { sum: result },
}));
});
// Set up listener for reply on Realm A's mailbox
let receivedReply: unknown = null;
backbone.subscribe(getLegacyIngressTopic(REALM_A), (topic, payload) => {
const parsed = JSON.parse(payload);
if (parsed.ok !== undefined) { // It's a reply
receivedReply = parsed;
}
});
await new Promise(r => setTimeout(r, 100));
// Realm A sends request to Realm B
const request = createLegacyRequest({
toRealm: REALM_B,
toPath: 'calculator.accepts.add',
fromRealm: REALM_A,
replyTo: '_client.inbox',
correlationId: 'cross-realm-123',
body: { a: 10, b: 32 },
});
// Publish to Realm B's mailbox on backbone
backbone.publish(getLegacyIngressTopic(REALM_B), serializeLegacyEnvelope(request));
// Wait for round-trip
await new Promise(r => setTimeout(r, 500));
// Verify reply was received
assert.ok(receivedReply, 'Should receive reply from Realm B');
assert.strictEqual((receivedReply as { ok: boolean }).ok, true, 'Reply should be ok');
assert.deepStrictEqual(
(receivedReply as { body: { sum: number } }).body,
{ sum: 42 },
'Sum should be 42'
);
console.log('✓ Cross-realm request/reply successful: 10 + 32 = 42');
gatewayA.stop();
gatewayB.stop();
});
it('Three realms: A → B → C chain', async () => {
const REALM_A = 'realm-a';
const REALM_B = 'realm-b';
const REALM_C = 'realm-c';
const backbone = new InMemoryFilterBroker();
const localBusA = new InMemoryFilterBroker();
const localBusB = new InMemoryFilterBroker();
const localBusC = new InMemoryFilterBroker();
const gatewayA = new FederationPeer({
localRealm: REALM_A,
profile: WIRE_PROFILES.matrix3,
backbone,
localBus: localBusA,
internalTimeoutMs: 5000,
});
const gatewayB = new FederationPeer({
localRealm: REALM_B,
profile: WIRE_PROFILES.matrix3,
backbone,
localBus: localBusB,
internalTimeoutMs: 5000,
});
const gatewayC = new FederationPeer({
localRealm: REALM_C,
profile: WIRE_PROFILES.matrix3,
backbone,
localBus: localBusC,
internalTimeoutMs: 5000,
});
gatewayA.start();
gatewayB.start();
gatewayC.start();
// Handler on Realm C
localBusC.subscribe(`service.accepts.echo`, (topic, payload) => {
const req = JSON.parse(payload) as { replyTo: string; correlationId: string; params: { msg: string } };
localBusC.publish(req.replyTo, JSON.stringify({
ok: true,
correlationId: req.correlationId,
result: { echo: `Echo from C: ${req.params.msg}` },
}));
});
// Collect replies at Realm A
let replyFromC: unknown = null;
backbone.subscribe(getLegacyIngressTopic(REALM_A), (topic, payload) => {
const parsed = JSON.parse(payload);
if (parsed.ok !== undefined) {
replyFromC = parsed;
}
});
await new Promise(r => setTimeout(r, 100));
// A sends directly to C (skipping B - this tests that each realm has its own mailbox)
const request = createLegacyRequest({
toRealm: REALM_C,
toPath: 'service.accepts.echo',
fromRealm: REALM_A,
replyTo: '_client.inbox',
correlationId: 'a-to-c-456',
body: { msg: 'hello from A' },
});
backbone.publish(getLegacyIngressTopic(REALM_C), serializeLegacyEnvelope(request));
await new Promise(r => setTimeout(r, 500));
assert.ok(replyFromC, 'Should receive reply from Realm C');
assert.strictEqual((replyFromC as { ok: boolean }).ok, true);
assert.deepStrictEqual(
(replyFromC as { body: { echo: string } }).body,
{ echo: 'Echo from C: hello from A' }
);
console.log('✓ Three-realm test passed: A → C direct communication');
gatewayA.stop();
gatewayB.stop();
gatewayC.stop();
});
it('Realm isolation: B cannot intercept messages for A', async () => {
const REALM_A = 'secure-realm-a';
const REALM_B = 'secure-realm-b';
const backbone = new InMemoryFilterBroker();
const localBusA = new InMemoryFilterBroker();
const localBusB = new InMemoryFilterBroker();
const gatewayA = new FederationPeer({
localRealm: REALM_A,
profile: WIRE_PROFILES.matrix3,
backbone,
localBus: localBusA,
});
const gatewayB = new FederationPeer({
localRealm: REALM_B,
profile: WIRE_PROFILES.matrix3,
backbone,
localBus: localBusB,
});
gatewayA.start();
gatewayB.start();
// Track what each realm's local bus receives
let realmAReceived = 0;
let realmBReceived = 0;
localBusA.subscribe(`secret.accepts.data`, () => {
realmAReceived++;
});
localBusB.subscribe(`secret.accepts.data`, () => {
realmBReceived++;
});
// Also try subscribing B to A's internal topic (should never fire)
localBusB.subscribe(`secret.accepts.data`, () => {
realmBReceived += 100; // Should never happen
});
await new Promise(r => setTimeout(r, 100));
// Send message to Realm A's mailbox
const request = createLegacyRequest({
toRealm: REALM_A,
toPath: 'secret.accepts.data',
fromRealm: 'external',
replyTo: '_inbox',
correlationId: 'secret-msg',
body: { secret: 'classified' },
});
backbone.publish(getLegacyIngressTopic(REALM_A), serializeLegacyEnvelope(request));
await new Promise(r => setTimeout(r, 300));
assert.strictEqual(realmAReceived, 1, 'Realm A should receive the message');
assert.strictEqual(realmBReceived, 0, 'Realm B should NOT receive messages for Realm A');
console.log('✓ Realm isolation verified: B cannot intercept A\'s messages');
gatewayA.stop();
gatewayB.stop();
});
});