870 lines
24 KiB
TypeScript
870 lines
24 KiB
TypeScript
|
|
/**
|
||
|
|
* Layer 2: Envelope Codec Tests
|
||
|
|
*
|
||
|
|
* Tests the envelope serialization/deserialization layer of the federation stack.
|
||
|
|
* Covers both Legacy Matrix-3 format and MXENV/1 canonical format.
|
||
|
|
*/
|
||
|
|
|
||
|
|
import test from 'node:test';
|
||
|
|
import assert from 'node:assert/strict';
|
||
|
|
import {
|
||
|
|
deserializeTaggedEnvelope,
|
||
|
|
createLegacyRequest,
|
||
|
|
createLegacyReply,
|
||
|
|
createMxEnvV1,
|
||
|
|
serializeLegacyEnvelope,
|
||
|
|
serializeMxEnvV1,
|
||
|
|
validateLegacyRequestEnvelope,
|
||
|
|
generateCorrelationId,
|
||
|
|
nowIso,
|
||
|
|
toErrorMessage,
|
||
|
|
} from '@open-matrix/federation/envelope_codec';
|
||
|
|
import type {
|
||
|
|
CrossRealmEnvelopeLegacy,
|
||
|
|
ReplyEnvelopeLegacy,
|
||
|
|
MxEnvelopeV1,
|
||
|
|
} from '@open-matrix/federation/envelope';
|
||
|
|
|
||
|
|
// ===== deserializeTaggedEnvelope tests =====
|
||
|
|
|
||
|
|
test('deserialize: detects valid MXENV/1 Cmd envelope', () => {
|
||
|
|
const envelope: MxEnvelopeV1 = {
|
||
|
|
ver: 1,
|
||
|
|
msgType: 'Cmd',
|
||
|
|
msgId: 'test-msg-id-123',
|
||
|
|
timestamp: '2026-01-27T12:00:00.000Z',
|
||
|
|
to: { root: 'target-realm', path: 'app.accepts.doSomething' },
|
||
|
|
from: { root: 'source-realm', path: '_client' },
|
||
|
|
body: { foo: 'bar' },
|
||
|
|
};
|
||
|
|
const json = JSON.stringify(envelope);
|
||
|
|
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
assert.equal(result.profile, 'mxenv1');
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.equal(result.envelope.msgType, 'Cmd');
|
||
|
|
assert.equal(result.envelope.to.root, 'target-realm');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: detects MXENV/1 Result envelope', () => {
|
||
|
|
const envelope: MxEnvelopeV1 = {
|
||
|
|
ver: 1,
|
||
|
|
msgType: 'Result',
|
||
|
|
msgId: 'result-123',
|
||
|
|
timestamp: '2026-01-27T12:00:00.000Z',
|
||
|
|
to: { root: 'source-realm', path: '_replies.xyz' },
|
||
|
|
from: { root: 'target-realm', path: 'app' },
|
||
|
|
correlationId: 'original-cmd-id',
|
||
|
|
body: { result: 'success' },
|
||
|
|
ok: true,
|
||
|
|
};
|
||
|
|
const json = JSON.stringify(envelope);
|
||
|
|
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
assert.equal(result.profile, 'mxenv1');
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.equal(result.envelope.msgType, 'Result');
|
||
|
|
assert.equal(result.envelope.ok, true);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: detects MXENV/1 Evt envelope', () => {
|
||
|
|
const envelope: MxEnvelopeV1 = {
|
||
|
|
ver: 1,
|
||
|
|
msgType: 'Evt',
|
||
|
|
msgId: 'evt-456',
|
||
|
|
timestamp: '2026-01-27T12:00:00.000Z',
|
||
|
|
to: { root: 'subscriber-realm', path: '_subscriptions.abc' },
|
||
|
|
from: { root: 'publisher-realm', path: 'component.emits.stateChanged' },
|
||
|
|
body: { state: 'active' },
|
||
|
|
};
|
||
|
|
const json = JSON.stringify(envelope);
|
||
|
|
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
assert.equal(result.profile, 'mxenv1');
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.equal(result.envelope.msgType, 'Evt');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: detects MXENV/1 with replyTo address', () => {
|
||
|
|
const envelope: MxEnvelopeV1 = {
|
||
|
|
ver: 1,
|
||
|
|
msgType: 'Cmd',
|
||
|
|
msgId: 'cmd-with-reply',
|
||
|
|
timestamp: '2026-01-27T12:00:00.000Z',
|
||
|
|
to: { root: 'target', path: 'svc.accepts.query' },
|
||
|
|
from: { root: 'source', path: 'client' },
|
||
|
|
replyTo: { root: 'source', path: '_replies.abc123' },
|
||
|
|
body: { query: 'SELECT *' },
|
||
|
|
};
|
||
|
|
const json = JSON.stringify(envelope);
|
||
|
|
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
assert.equal(result.profile, 'mxenv1');
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.deepEqual(result.envelope.replyTo, { root: 'source', path: '_replies.abc123' });
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: detects MXENV/1 with error', () => {
|
||
|
|
const envelope: MxEnvelopeV1 = {
|
||
|
|
ver: 1,
|
||
|
|
msgType: 'Result',
|
||
|
|
msgId: 'err-result',
|
||
|
|
timestamp: '2026-01-27T12:00:00.000Z',
|
||
|
|
to: { root: 'source', path: '_replies.xyz' },
|
||
|
|
from: { root: 'target', path: 'svc' },
|
||
|
|
correlationId: 'original-123',
|
||
|
|
body: null,
|
||
|
|
ok: false,
|
||
|
|
error: {
|
||
|
|
code: 'MX.AUTH.FORBIDDEN',
|
||
|
|
message: 'Access denied',
|
||
|
|
details: { requiredScope: 'admin' },
|
||
|
|
},
|
||
|
|
};
|
||
|
|
const json = JSON.stringify(envelope);
|
||
|
|
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
assert.equal(result.profile, 'mxenv1');
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.equal(result.envelope.ok, false);
|
||
|
|
assert.equal(result.envelope.error?.code, 'MX.AUTH.FORBIDDEN');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: detects valid legacy request envelope', () => {
|
||
|
|
const envelope: CrossRealmEnvelopeLegacy = {
|
||
|
|
toRealm: 'matrix-3',
|
||
|
|
toPath: 'daemon.accepts.introspect',
|
||
|
|
fromRealm: 'flowpad',
|
||
|
|
replyTo: '_replies.emits.abc123',
|
||
|
|
correlationId: 'corr-123',
|
||
|
|
body: {},
|
||
|
|
timestamp: '2026-01-27T12:00:00.000Z',
|
||
|
|
};
|
||
|
|
const json = JSON.stringify(envelope);
|
||
|
|
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
assert.equal(result.profile, 'matrix3');
|
||
|
|
if (result.profile === 'matrix3') {
|
||
|
|
assert.equal(result.kind, 'request');
|
||
|
|
assert.equal(result.envelope.toRealm, 'matrix-3');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: detects legacy request with event type', () => {
|
||
|
|
const envelope: CrossRealmEnvelopeLegacy = {
|
||
|
|
toRealm: 'subscriber-realm',
|
||
|
|
toPath: 'component.accepts.handleEvent',
|
||
|
|
fromRealm: 'publisher-realm',
|
||
|
|
replyTo: 'none',
|
||
|
|
correlationId: 'evt-corr-456',
|
||
|
|
body: { event: 'click' },
|
||
|
|
type: 'event',
|
||
|
|
};
|
||
|
|
const json = JSON.stringify(envelope);
|
||
|
|
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
assert.equal(result.profile, 'matrix3');
|
||
|
|
if (result.profile === 'matrix3') {
|
||
|
|
assert.equal(result.kind, 'request');
|
||
|
|
assert.equal((result.envelope as CrossRealmEnvelopeLegacy).type, 'event');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: detects legacy reply with ok=true', () => {
|
||
|
|
const envelope: ReplyEnvelopeLegacy = {
|
||
|
|
toRealm: 'flowpad',
|
||
|
|
toPath: '_replies.emits.abc123',
|
||
|
|
fromRealm: 'matrix-3',
|
||
|
|
correlationId: 'corr-123',
|
||
|
|
body: { children: [] },
|
||
|
|
ok: true,
|
||
|
|
timestamp: '2026-01-27T12:00:01.000Z',
|
||
|
|
};
|
||
|
|
const json = JSON.stringify(envelope);
|
||
|
|
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
assert.equal(result.profile, 'matrix3');
|
||
|
|
if (result.profile === 'matrix3') {
|
||
|
|
assert.equal(result.kind, 'reply');
|
||
|
|
assert.equal((result.envelope as ReplyEnvelopeLegacy).ok, true);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: detects legacy reply with ok=false and error', () => {
|
||
|
|
const envelope: ReplyEnvelopeLegacy = {
|
||
|
|
toRealm: 'flowpad',
|
||
|
|
toPath: '_replies.emits.xyz',
|
||
|
|
fromRealm: 'matrix-3',
|
||
|
|
correlationId: 'err-corr',
|
||
|
|
body: null,
|
||
|
|
ok: false,
|
||
|
|
error: {
|
||
|
|
code: 'MX.TIMEOUT',
|
||
|
|
message: 'Request timed out',
|
||
|
|
},
|
||
|
|
};
|
||
|
|
const json = JSON.stringify(envelope);
|
||
|
|
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
assert.equal(result.profile, 'matrix3');
|
||
|
|
if (result.profile === 'matrix3' && result.kind === 'reply') {
|
||
|
|
assert.equal(result.envelope.ok, false);
|
||
|
|
assert.equal(result.envelope.error?.code, 'MX.TIMEOUT');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: returns null for invalid JSON', () => {
|
||
|
|
const result = deserializeTaggedEnvelope('not valid json {{{');
|
||
|
|
assert.equal(result, null);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: returns null for empty object', () => {
|
||
|
|
const result = deserializeTaggedEnvelope('{}');
|
||
|
|
assert.equal(result, null);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: returns null for array', () => {
|
||
|
|
const result = deserializeTaggedEnvelope('[1, 2, 3]');
|
||
|
|
assert.equal(result, null);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: returns null for primitive values', () => {
|
||
|
|
assert.equal(deserializeTaggedEnvelope('"string"'), null);
|
||
|
|
assert.equal(deserializeTaggedEnvelope('123'), null);
|
||
|
|
assert.equal(deserializeTaggedEnvelope('null'), null);
|
||
|
|
assert.equal(deserializeTaggedEnvelope('true'), null);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: returns null for MXENV/1 with invalid ver', () => {
|
||
|
|
const envelope = {
|
||
|
|
ver: 2, // Wrong version
|
||
|
|
msgType: 'Cmd',
|
||
|
|
msgId: 'id',
|
||
|
|
timestamp: 'ts',
|
||
|
|
to: { realm: 'r', path: 'p' },
|
||
|
|
from: { realm: 'r', path: 'p' },
|
||
|
|
body: {},
|
||
|
|
};
|
||
|
|
const result = deserializeTaggedEnvelope(JSON.stringify(envelope));
|
||
|
|
assert.equal(result, null);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: returns null for MXENV/1 with invalid msgType', () => {
|
||
|
|
const envelope = {
|
||
|
|
ver: 1,
|
||
|
|
msgType: 'InvalidType',
|
||
|
|
msgId: 'id',
|
||
|
|
timestamp: 'ts',
|
||
|
|
to: { realm: 'r', path: 'p' },
|
||
|
|
from: { realm: 'r', path: 'p' },
|
||
|
|
body: {},
|
||
|
|
};
|
||
|
|
const result = deserializeTaggedEnvelope(JSON.stringify(envelope));
|
||
|
|
assert.equal(result, null);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('deserialize: returns null for legacy request missing correlationId', () => {
|
||
|
|
const envelope = {
|
||
|
|
toRealm: 'target',
|
||
|
|
toPath: 'path.accepts.op',
|
||
|
|
fromRealm: 'source',
|
||
|
|
replyTo: '_replies',
|
||
|
|
// Missing correlationId
|
||
|
|
body: {},
|
||
|
|
};
|
||
|
|
const result = deserializeTaggedEnvelope(JSON.stringify(envelope));
|
||
|
|
assert.equal(result, null);
|
||
|
|
});
|
||
|
|
|
||
|
|
// ===== createLegacyRequest tests =====
|
||
|
|
|
||
|
|
test('createLegacyRequest: creates request with all required fields', () => {
|
||
|
|
const request = createLegacyRequest({
|
||
|
|
toRealm: 'target-realm',
|
||
|
|
toPath: 'service.accepts.doWork',
|
||
|
|
fromRealm: 'source-realm',
|
||
|
|
replyTo: '_replies.emits.callback123',
|
||
|
|
body: { data: 'test' },
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(request.toRealm, 'target-realm');
|
||
|
|
assert.equal(request.toPath, 'service.accepts.doWork');
|
||
|
|
assert.equal(request.fromRealm, 'source-realm');
|
||
|
|
assert.equal(request.replyTo, '_replies.emits.callback123');
|
||
|
|
assert.deepEqual(request.body, { data: 'test' });
|
||
|
|
assert.ok(typeof request.correlationId === 'string');
|
||
|
|
assert.ok(typeof request.timestamp === 'string');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('createLegacyRequest: uses provided correlationId', () => {
|
||
|
|
const request = createLegacyRequest({
|
||
|
|
toRealm: 'target',
|
||
|
|
toPath: 'path.accepts.op',
|
||
|
|
fromRealm: 'source',
|
||
|
|
replyTo: 'reply',
|
||
|
|
correlationId: 'my-custom-correlation-id',
|
||
|
|
body: {},
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(request.correlationId, 'my-custom-correlation-id');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('createLegacyRequest: includes optional fields when provided', () => {
|
||
|
|
const request = createLegacyRequest({
|
||
|
|
toRealm: 'target',
|
||
|
|
toPath: 'path.accepts.op',
|
||
|
|
fromRealm: 'source',
|
||
|
|
replyTo: 'reply',
|
||
|
|
body: {},
|
||
|
|
ttlMs: 5000,
|
||
|
|
traceId: 'trace-abc',
|
||
|
|
type: 'event',
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(request.ttlMs, 5000);
|
||
|
|
assert.equal(request.traceId, 'trace-abc');
|
||
|
|
assert.equal(request.type, 'event');
|
||
|
|
});
|
||
|
|
|
||
|
|
// ===== createLegacyReply tests =====
|
||
|
|
|
||
|
|
test('createLegacyReply: creates successful reply', () => {
|
||
|
|
const baseRequest: CrossRealmEnvelopeLegacy = {
|
||
|
|
toRealm: 'target-realm',
|
||
|
|
toPath: 'service.accepts.query',
|
||
|
|
fromRealm: 'source-realm',
|
||
|
|
replyTo: '_replies.emits.callback456',
|
||
|
|
correlationId: 'original-correlation-id',
|
||
|
|
body: { query: 'SELECT *' },
|
||
|
|
};
|
||
|
|
|
||
|
|
const reply = createLegacyReply({
|
||
|
|
request: baseRequest,
|
||
|
|
responderRealm: 'target-realm',
|
||
|
|
body: { results: [1, 2, 3] },
|
||
|
|
ok: true,
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(reply.toRealm, 'source-realm'); // Swapped to fromRealm of request
|
||
|
|
assert.equal(reply.toPath, '_replies.emits.callback456'); // Uses replyTo from request
|
||
|
|
assert.equal(reply.fromRealm, 'target-realm');
|
||
|
|
assert.equal(reply.correlationId, 'original-correlation-id');
|
||
|
|
assert.deepEqual(reply.body, { results: [1, 2, 3] });
|
||
|
|
assert.equal(reply.ok, true);
|
||
|
|
assert.equal(reply.error, undefined);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('createLegacyReply: creates error reply', () => {
|
||
|
|
const baseRequest: CrossRealmEnvelopeLegacy = {
|
||
|
|
toRealm: 'target-realm',
|
||
|
|
toPath: 'service.accepts.query',
|
||
|
|
fromRealm: 'source-realm',
|
||
|
|
replyTo: '_replies.emits.callback456',
|
||
|
|
correlationId: 'original-correlation-id',
|
||
|
|
body: {},
|
||
|
|
};
|
||
|
|
|
||
|
|
const reply = createLegacyReply({
|
||
|
|
request: baseRequest,
|
||
|
|
responderRealm: 'target-realm',
|
||
|
|
body: null,
|
||
|
|
ok: false,
|
||
|
|
error: {
|
||
|
|
code: 'MX.NOT_FOUND',
|
||
|
|
message: 'Resource not found',
|
||
|
|
details: { id: 'abc123' },
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(reply.ok, false);
|
||
|
|
assert.deepEqual(reply.error, {
|
||
|
|
code: 'MX.NOT_FOUND',
|
||
|
|
message: 'Resource not found',
|
||
|
|
details: { id: 'abc123' },
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// ===== createMxEnvV1 tests =====
|
||
|
|
|
||
|
|
test('createMxEnvV1: creates Cmd envelope', () => {
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType: 'Cmd',
|
||
|
|
toRoot: 'target',
|
||
|
|
toPath: 'service.accepts.execute',
|
||
|
|
fromRoot: 'source',
|
||
|
|
body: { command: 'run' },
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(envelope.ver, 1);
|
||
|
|
assert.equal(envelope.msgType, 'Cmd');
|
||
|
|
assert.equal(envelope.to.root, 'target');
|
||
|
|
assert.equal(envelope.to.path, 'service.accepts.execute');
|
||
|
|
assert.equal(envelope.from.root, 'source');
|
||
|
|
assert.equal(envelope.from.path, '_client'); // Default
|
||
|
|
assert.deepEqual(envelope.body, { command: 'run' });
|
||
|
|
assert.ok(typeof envelope.msgId === 'string');
|
||
|
|
assert.ok(typeof envelope.timestamp === 'string');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('createMxEnvV1: creates Result envelope', () => {
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType: 'Result',
|
||
|
|
toRoot: 'source',
|
||
|
|
toPath: '_replies.abc123',
|
||
|
|
fromRoot: 'target',
|
||
|
|
fromPath: 'service',
|
||
|
|
correlationId: 'original-cmd-id',
|
||
|
|
body: { data: 'result' },
|
||
|
|
ok: true,
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(envelope.msgType, 'Result');
|
||
|
|
assert.equal(envelope.correlationId, 'original-cmd-id');
|
||
|
|
assert.equal(envelope.ok, true);
|
||
|
|
assert.equal(envelope.from.path, 'service');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('createMxEnvV1: includes replyTo when provided', () => {
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType: 'Cmd',
|
||
|
|
toRoot: 'target',
|
||
|
|
toPath: 'svc.accepts.query',
|
||
|
|
fromRoot: 'source',
|
||
|
|
replyToRoot: 'source',
|
||
|
|
replyToPath: '_replies.callback789',
|
||
|
|
body: {},
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(envelope.replyTo!.root, 'source');
|
||
|
|
assert.equal(envelope.replyTo!.path, '_replies.callback789');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('createMxEnvV1: includes error for failed Result', () => {
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType: 'Result',
|
||
|
|
toRoot: 'source',
|
||
|
|
toPath: '_replies.abc',
|
||
|
|
fromRoot: 'target',
|
||
|
|
body: null,
|
||
|
|
ok: false,
|
||
|
|
error: {
|
||
|
|
code: 'MX.INTERNAL',
|
||
|
|
message: 'Internal error',
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(envelope.ok, false);
|
||
|
|
assert.equal(envelope.error?.code, 'MX.INTERNAL');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('createMxEnvV1: includes ttl when provided', () => {
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType: 'Cmd',
|
||
|
|
toRoot: 'target',
|
||
|
|
toPath: 'path.accepts.op',
|
||
|
|
fromRoot: 'source',
|
||
|
|
body: {},
|
||
|
|
ttl: 5,
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(envelope.ttl, 5);
|
||
|
|
});
|
||
|
|
|
||
|
|
// ===== validateLegacyRequestEnvelope tests =====
|
||
|
|
|
||
|
|
test('validate: passes for valid envelope with accepts path', () => {
|
||
|
|
const envelope: CrossRealmEnvelopeLegacy = {
|
||
|
|
toRoot: 'target',
|
||
|
|
toPath: 'service.accepts.query',
|
||
|
|
fromRoot: 'source',
|
||
|
|
replyTo: '_replies.xyz',
|
||
|
|
correlationId: 'corr-123',
|
||
|
|
body: {},
|
||
|
|
};
|
||
|
|
|
||
|
|
const result = validateLegacyRequestEnvelope(envelope);
|
||
|
|
assert.equal(result.ok, true);
|
||
|
|
assert.equal(result.error, undefined);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('validate: passes for valid envelope with emits path', () => {
|
||
|
|
const envelope: CrossRealmEnvelopeLegacy = {
|
||
|
|
toRoot: 'target',
|
||
|
|
toPath: 'component.emits.stateChanged',
|
||
|
|
fromRoot: 'source',
|
||
|
|
replyTo: '_sub.xyz',
|
||
|
|
correlationId: 'corr-456',
|
||
|
|
body: {},
|
||
|
|
};
|
||
|
|
|
||
|
|
const result = validateLegacyRequestEnvelope(envelope);
|
||
|
|
assert.equal(result.ok, true);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('validate: fails for missing toRoot', () => {
|
||
|
|
const envelope = {
|
||
|
|
toPath: 'service.accepts.query',
|
||
|
|
fromRoot: 'source',
|
||
|
|
replyTo: '_replies.xyz',
|
||
|
|
correlationId: 'corr-123',
|
||
|
|
body: {},
|
||
|
|
} as unknown as CrossRealmEnvelopeLegacy;
|
||
|
|
|
||
|
|
const result = validateLegacyRequestEnvelope(envelope);
|
||
|
|
assert.equal(result.ok, false);
|
||
|
|
assert.ok(result.error?.includes('toRoot'));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('validate: fails for empty toPath', () => {
|
||
|
|
const envelope: CrossRealmEnvelopeLegacy = {
|
||
|
|
toRoot: 'target',
|
||
|
|
toPath: '',
|
||
|
|
fromRoot: 'source',
|
||
|
|
replyTo: '_replies.xyz',
|
||
|
|
correlationId: 'corr-123',
|
||
|
|
body: {},
|
||
|
|
};
|
||
|
|
|
||
|
|
const result = validateLegacyRequestEnvelope(envelope);
|
||
|
|
assert.equal(result.ok, false);
|
||
|
|
assert.ok(result.error?.includes('toPath'));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('validate: fails for toPath without .accepts. or .emits.', () => {
|
||
|
|
const envelope: CrossRealmEnvelopeLegacy = {
|
||
|
|
toRoot: 'target',
|
||
|
|
toPath: 'service.query', // Missing plane token
|
||
|
|
fromRoot: 'source',
|
||
|
|
replyTo: '_replies.xyz',
|
||
|
|
correlationId: 'corr-123',
|
||
|
|
body: {},
|
||
|
|
};
|
||
|
|
|
||
|
|
const result = validateLegacyRequestEnvelope(envelope);
|
||
|
|
assert.equal(result.ok, false);
|
||
|
|
assert.ok(result.error?.includes('.accepts.'));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('validate: fails for null envelope', () => {
|
||
|
|
const result = validateLegacyRequestEnvelope(null as unknown as CrossRealmEnvelopeLegacy);
|
||
|
|
assert.equal(result.ok, false);
|
||
|
|
assert.ok(result.error?.includes('not an object'));
|
||
|
|
});
|
||
|
|
|
||
|
|
// ===== Round-trip tests =====
|
||
|
|
|
||
|
|
test('roundtrip: legacy request', () => {
|
||
|
|
const original = createLegacyRequest({
|
||
|
|
toRealm: 'target-realm',
|
||
|
|
toPath: 'service.accepts.execute',
|
||
|
|
fromRealm: 'source-realm',
|
||
|
|
replyTo: '_replies.emits.cb123',
|
||
|
|
body: { nested: { data: [1, 2, 3] } },
|
||
|
|
ttlMs: 10000,
|
||
|
|
traceId: 'trace-abc',
|
||
|
|
});
|
||
|
|
|
||
|
|
const json = serializeLegacyEnvelope(original);
|
||
|
|
const deserialized = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(deserialized !== null);
|
||
|
|
assert.equal(deserialized.profile, 'matrix3');
|
||
|
|
if (deserialized.profile === 'matrix3' && deserialized.kind === 'request') {
|
||
|
|
assert.equal(deserialized.envelope.toRealm, original.toRealm);
|
||
|
|
assert.equal(deserialized.envelope.toPath, original.toPath);
|
||
|
|
assert.equal(deserialized.envelope.fromRealm, original.fromRealm);
|
||
|
|
assert.equal(deserialized.envelope.correlationId, original.correlationId);
|
||
|
|
assert.deepEqual(deserialized.envelope.body, original.body);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('roundtrip: legacy reply', () => {
|
||
|
|
const request = createLegacyRequest({
|
||
|
|
toRealm: 'target',
|
||
|
|
toPath: 'svc.accepts.op',
|
||
|
|
fromRealm: 'source',
|
||
|
|
replyTo: '_replies.xyz',
|
||
|
|
body: {},
|
||
|
|
});
|
||
|
|
|
||
|
|
const original = createLegacyReply({
|
||
|
|
request,
|
||
|
|
responderRealm: 'target',
|
||
|
|
body: { status: 'done' },
|
||
|
|
ok: true,
|
||
|
|
});
|
||
|
|
|
||
|
|
const json = serializeLegacyEnvelope(original);
|
||
|
|
const deserialized = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(deserialized !== null);
|
||
|
|
assert.equal(deserialized.profile, 'matrix3');
|
||
|
|
if (deserialized.profile === 'matrix3' && deserialized.kind === 'reply') {
|
||
|
|
assert.equal(deserialized.envelope.ok, true);
|
||
|
|
assert.deepEqual(deserialized.envelope.body, { status: 'done' });
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('roundtrip: MXENV/1 Cmd', () => {
|
||
|
|
const original = createMxEnvV1({
|
||
|
|
msgType: 'Cmd',
|
||
|
|
toRoot: 'target',
|
||
|
|
toPath: 'svc.accepts.execute',
|
||
|
|
fromRoot: 'source',
|
||
|
|
fromPath: 'client.app',
|
||
|
|
replyToRoot: 'source',
|
||
|
|
replyToPath: '_replies.callback123',
|
||
|
|
body: { command: 'test', args: [1, 2, 3] },
|
||
|
|
ttl: 3,
|
||
|
|
});
|
||
|
|
|
||
|
|
const json = serializeMxEnvV1(original);
|
||
|
|
const deserialized = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(deserialized !== null);
|
||
|
|
assert.equal(deserialized.profile, 'mxenv1');
|
||
|
|
if (deserialized.profile === 'mxenv1') {
|
||
|
|
assert.equal(deserialized.envelope.msgType, 'Cmd');
|
||
|
|
assert.equal(deserialized.envelope.to.root, original.to.root);
|
||
|
|
assert.equal(deserialized.envelope.to.path, original.to.path);
|
||
|
|
assert.equal(deserialized.envelope.from.root, original.from.root);
|
||
|
|
assert.equal(deserialized.envelope.from.path, original.from.path);
|
||
|
|
assert.equal(deserialized.envelope.replyTo!.root, original.replyTo!.root);
|
||
|
|
assert.equal(deserialized.envelope.replyTo!.path, original.replyTo!.path);
|
||
|
|
assert.deepEqual(deserialized.envelope.body, original.body);
|
||
|
|
assert.equal(deserialized.envelope.ttl, 3);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('roundtrip: MXENV/1 Result with error', () => {
|
||
|
|
const original = createMxEnvV1({
|
||
|
|
msgType: 'Result',
|
||
|
|
toRoot: 'source',
|
||
|
|
toPath: '_replies.xyz',
|
||
|
|
fromRoot: 'target',
|
||
|
|
correlationId: 'cmd-123',
|
||
|
|
body: null,
|
||
|
|
ok: false,
|
||
|
|
error: {
|
||
|
|
code: 'MX.AUTH.FORBIDDEN',
|
||
|
|
message: 'Permission denied',
|
||
|
|
details: { missingScope: 'admin' },
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
const json = serializeMxEnvV1(original);
|
||
|
|
const deserialized = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(deserialized !== null);
|
||
|
|
assert.equal(deserialized.profile, 'mxenv1');
|
||
|
|
if (deserialized.profile === 'mxenv1') {
|
||
|
|
assert.equal(deserialized.envelope.ok, false);
|
||
|
|
assert.deepEqual(deserialized.envelope.error, original.error);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// ===== Utility function tests =====
|
||
|
|
|
||
|
|
test('generateCorrelationId: generates unique IDs', () => {
|
||
|
|
const id1 = generateCorrelationId();
|
||
|
|
const id2 = generateCorrelationId();
|
||
|
|
|
||
|
|
assert.ok(typeof id1 === 'string');
|
||
|
|
assert.ok(typeof id2 === 'string');
|
||
|
|
assert.notEqual(id1, id2);
|
||
|
|
assert.ok(id1.length > 0);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('nowIso: returns valid ISO timestamp', () => {
|
||
|
|
const ts = nowIso();
|
||
|
|
assert.ok(typeof ts === 'string');
|
||
|
|
// Should be parseable as a date
|
||
|
|
const parsed = new Date(ts);
|
||
|
|
assert.ok(!isNaN(parsed.getTime()));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('nowIso: returns current time', () => {
|
||
|
|
const before = Date.now();
|
||
|
|
const ts = nowIso();
|
||
|
|
const after = Date.now();
|
||
|
|
|
||
|
|
const tsMs = new Date(ts).getTime();
|
||
|
|
assert.ok(tsMs >= before);
|
||
|
|
assert.ok(tsMs <= after);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('toErrorMessage: extracts message from Error', () => {
|
||
|
|
const error = new Error('Something went wrong');
|
||
|
|
assert.equal(toErrorMessage(error), 'Something went wrong');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('toErrorMessage: converts string to message', () => {
|
||
|
|
assert.equal(toErrorMessage('plain string error'), 'plain string error');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('toErrorMessage: handles null', () => {
|
||
|
|
// null => JSON.stringify(null) => "null" (string)
|
||
|
|
assert.ok(typeof toErrorMessage(null) === 'string');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('toErrorMessage: handles objects', () => {
|
||
|
|
const result = toErrorMessage({ custom: 'error' });
|
||
|
|
assert.ok(typeof result === 'string');
|
||
|
|
});
|
||
|
|
|
||
|
|
// ===== All msgType values tests =====
|
||
|
|
|
||
|
|
const msgTypes = ['Cmd', 'Evt', 'Result', 'Sub', 'Unsub', 'Nack'] as const;
|
||
|
|
|
||
|
|
for (const msgType of msgTypes) {
|
||
|
|
test(`msgType: creates and deserializes ${msgType} envelope`, () => {
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType,
|
||
|
|
toRoot: 'target',
|
||
|
|
toPath: 'path.accepts.op',
|
||
|
|
fromRoot: 'source',
|
||
|
|
body: { type: msgType },
|
||
|
|
});
|
||
|
|
|
||
|
|
const json = serializeMxEnvV1(envelope);
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
assert.equal(result.profile, 'mxenv1');
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.equal(result.envelope.msgType, msgType);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// ===== Edge case tests =====
|
||
|
|
|
||
|
|
test('edge: handles body with complex nested structures', () => {
|
||
|
|
const complexBody = {
|
||
|
|
array: [1, 'two', { three: 3 }],
|
||
|
|
nested: {
|
||
|
|
deep: {
|
||
|
|
deeper: {
|
||
|
|
value: 'found',
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
special: null,
|
||
|
|
boolean: true,
|
||
|
|
number: 42.5,
|
||
|
|
};
|
||
|
|
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType: 'Cmd',
|
||
|
|
toRealm: 'target',
|
||
|
|
toPath: 'svc.accepts.complex',
|
||
|
|
fromRealm: 'source',
|
||
|
|
body: complexBody,
|
||
|
|
});
|
||
|
|
|
||
|
|
const json = serializeMxEnvV1(envelope);
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.deepEqual(result.envelope.body, complexBody);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('edge: handles empty body', () => {
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType: 'Cmd',
|
||
|
|
toRealm: 'target',
|
||
|
|
toPath: 'svc.accepts.ping',
|
||
|
|
fromRealm: 'source',
|
||
|
|
body: {},
|
||
|
|
});
|
||
|
|
|
||
|
|
const json = serializeMxEnvV1(envelope);
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.deepEqual(result.envelope.body, {});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('edge: handles null body', () => {
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType: 'Result',
|
||
|
|
toRealm: 'target',
|
||
|
|
toPath: '_replies.xyz',
|
||
|
|
fromRealm: 'source',
|
||
|
|
body: null,
|
||
|
|
ok: true,
|
||
|
|
});
|
||
|
|
|
||
|
|
const json = serializeMxEnvV1(envelope);
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.equal(result.envelope.body, null);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('edge: handles unicode in body', () => {
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType: 'Cmd',
|
||
|
|
toRealm: 'target',
|
||
|
|
toPath: 'svc.accepts.unicode',
|
||
|
|
fromRealm: 'source',
|
||
|
|
body: { message: '你好世界 🌍 مرحبا' },
|
||
|
|
});
|
||
|
|
|
||
|
|
const json = serializeMxEnvV1(envelope);
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.equal((result.envelope.body as any).message, '你好世界 🌍 مرحبا');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('edge: handles very long paths', () => {
|
||
|
|
const longPath = 'a'.repeat(100) + '.accepts.' + 'b'.repeat(100);
|
||
|
|
const envelope = createMxEnvV1({
|
||
|
|
msgType: 'Cmd',
|
||
|
|
toRealm: 'target',
|
||
|
|
toPath: longPath,
|
||
|
|
fromRealm: 'source',
|
||
|
|
body: {},
|
||
|
|
});
|
||
|
|
|
||
|
|
const json = serializeMxEnvV1(envelope);
|
||
|
|
const result = deserializeTaggedEnvelope(json);
|
||
|
|
|
||
|
|
assert.ok(result !== null);
|
||
|
|
if (result.profile === 'mxenv1') {
|
||
|
|
assert.equal(result.envelope.to.path, longPath);
|
||
|
|
}
|
||
|
|
});
|