123 lines
4.6 KiB
TypeScript
Raw Permalink Normal View History

import test from 'node:test';
import assert from 'node:assert/strict';
import { InMemoryExactBroker, InMemoryFilterBroker } from '@open-matrix/federation/transport/inmem';
import { FederationPeer, ExactInstanceResolver } from '@open-matrix/federation/federation_peer';
import { getInternalTopic, getLegacyIngressTopic } from '@open-matrix/federation/topics';
import { createLegacyRequest, deserializeTaggedEnvelope, serializeLegacyEnvelope } from '@open-matrix/federation/envelope_codec';
import { parseMatrixUri } from '@open-matrix/federation/uri';
import { isRecord } from '../../src/util/guards';
import type { Transport } from '@open-matrix/federation/transport/base';
test('matrix3 compat: legacy request with ttlMs + flat replyTo is accepted and produces a reply', async () => {
const backbone: Transport = new InMemoryExactBroker();
const localBus = new InMemoryFilterBroker();
const serverRealm = 'matrix-3';
const clientRealm = 'flowpad-demo.tab-01';
// Start EdgeGateway (server-side)
const edge = new FederationPeer({
localRealm: serverRealm,
backbone,
localBus,
});
edge.start();
// Local handler (no helper wrappers) that replies with a NON-standard reply payload
// to prove lenient decoding on the EdgeGateway.
const toPath = 'project/daemon.project.accepts.scan';
const internalTopic = getInternalTopic(serverRealm, toPath);
localBus.subscribe(internalTopic, (_t, raw) => {
const parsed = (() => {
try {
return JSON.parse(raw) as unknown;
} catch {
return null;
}
})();
if (!isRecord(parsed)) throw new Error('internal request must be a JSON object');
const replyTo = parsed.replyTo;
if (typeof replyTo !== 'string') throw new Error('replyTo must be a string');
// Reply with `{ result: ... }` only (no correlationId, no ok), to exercise lenient reply parsing.
localBus.publish(replyTo, JSON.stringify({ result: { hello: true } }));
});
// Client mailbox watcher
const clientMailbox = getLegacyIngressTopic(clientRealm);
const serverMailbox = getLegacyIngressTopic(serverRealm);
const correlationId = 'cid-ttlms-001';
const replyToPath = `_replies.emits.${correlationId}`;
const repPromise = new Promise<unknown>((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('timeout waiting for reply')), 250);
const unsub = backbone.subscribe(clientMailbox, (_topic, payload) => {
clearTimeout(timer);
unsub();
const tagged = deserializeTaggedEnvelope(payload);
if (!tagged) throw new Error('expected an envelope');
if (tagged.profile !== 'matrix3') throw new Error('expected matrix3 envelope');
if (tagged.kind !== 'reply') throw new Error('expected matrix3 reply envelope');
resolve(tagged.envelope.body);
});
});
// Send raw legacy request with ttlMs (expiry semantics) and flat replyTo
const req = createLegacyRequest({
toRealm: serverRealm,
toPath,
fromRealm: clientRealm,
replyTo: replyToPath,
correlationId,
body: { depth: 1 },
ttlMs: 1234,
type: 'request',
});
backbone.publish(serverMailbox, serializeLegacyEnvelope(req));
const body = await repPromise;
assert.deepEqual(body, { hello: true });
});
test('matrix3 compat: reply detection works for ok:true and ok:false', () => {
const okRep = JSON.stringify({
toRealm: 'a',
toPath: '_replies.emits.x',
fromRealm: 'b',
correlationId: 'x',
ok: true,
body: { v: 1 },
});
const badRep = JSON.stringify({
toRealm: 'a',
toPath: '_replies.emits.x',
fromRealm: 'b',
correlationId: 'x',
ok: false,
body: null,
error: { code: 'MX.FAIL', message: 'nope' },
});
const t1 = deserializeTaggedEnvelope(okRep);
if (!t1) throw new Error('expected non-null');
if (t1.profile !== 'matrix3') throw new Error('expected matrix3 profile');
if (t1.kind !== 'reply') throw new Error('expected reply');
const t2 = deserializeTaggedEnvelope(badRep);
if (!t2) throw new Error('expected non-null');
if (t2.profile !== 'matrix3') throw new Error('expected matrix3 profile');
if (t2.kind !== 'reply') throw new Error('expected reply');
});
test('matrix3 compat: URI parsing tolerant (legacy vs /-/ delimiter) canonicalizes to same toPath', () => {
const a = parseMatrixUri('matrix-3/project/daemon.project.accepts.scan');
const b = parseMatrixUri('matrix-3/project/-/daemon/project/accepts/scan');
if (!a) throw new Error('expected non-null');
if (!b) throw new Error('expected non-null');
assert.equal(a.realm, 'matrix-3');
assert.equal(b.realm, 'matrix-3');
assert.equal(a.toPath, b.toPath);
});