CultLib/packages/cultnet-ts/test/cultnet.test.ts
2026-08-18 00:05:57 +02:00

1675 lines
61 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import { EventEmitter } from "node:events";
import { Duplex } from "node:stream";
import dgram, { type Socket } from "node:dgram";
import { rmSync, mkdtempSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { z } from "zod";
import {
CultCache,
SingleFileMessagePackBackingStore,
defineDocumentType,
} from "cultcache-ts";
import {
CultNetClientSecurityOptions,
CultNetDocumentRegistry,
CultNetPeer,
CultNetRudpReconnectLoop,
CultNetRudpSession,
CultNetRudpSocketTransportConnection,
CultNetSchemaCatalog,
CultNetSchemaRegistry,
CultNetSecret,
CultNetServerSecurityOptions,
CultNetShardCatalog,
TcpFramedTransportConnection,
CultNetReconnectController,
cultNetSchemas,
cultNetBuiltinSchemaRegistry,
computeCultNetReconnectDelayMs,
createCultNetReconnectPolicy,
createTcpFramedCultNetPeer,
createTcpFramedTransportProfile,
createRudpTransportProfile,
defineCultNetDocumentBinding,
decodeRudpPacket,
encodeCultNetMessageForWire,
encodeRudpPacket,
ghostlightAgentStateGeneratedContract,
parseCultNetMessage,
invokeCultNetOperation,
startCultNetOperationServer,
validateGhostlightAgentStateGenerated,
validateGhostlightAgentState,
shardServes,
type CultNetLoginMessage,
type GhostlightAgentStateShape,
type GhostlightAgentStateDocument,
} from "../src";
import {
INTEROP_SCHEMA_VERSION,
createInteropFormatter,
createLegacyInteropNoteFormatter,
createMismatchedInteropNoteFormatter,
type InteropNote,
} from "./interop/cultnet-interop-shared";
class FakeRudpReconnectTransport extends EventEmitter {
public connectCalls = 0;
public closeCalls = 0;
public lastPayload: Uint8Array | undefined;
public connect(payload = new Uint8Array()): void {
this.connectCalls += 1;
this.lastPayload = payload;
}
public close(): void {
this.closeCalls += 1;
this.emit("close");
}
}
class LinkedDuplex extends Duplex {
peer?: LinkedDuplex;
// eslint-disable-next-line @typescript-eslint/no-empty-function
_read(): void {}
_write(
chunk: Buffer,
_encoding: BufferEncoding,
callback: (error?: Error | null) => void,
): void {
this.peer?.push(Buffer.from(chunk));
callback();
}
_final(callback: (error?: Error | null) => void): void {
this.peer?.push(null);
callback();
}
}
function createDuplexPair(): { a: Duplex; b: Duplex } {
const a = new LinkedDuplex();
const b = new LinkedDuplex();
a.peer = b;
b.peer = a;
return { a, b };
}
async function bindUdpSocket(): Promise<Socket> {
const socket = dgram.createSocket("udp4");
await new Promise<void>((resolve) => socket.bind(0, "127.0.0.1", resolve));
return socket;
}
function udpPort(socket: Socket): number {
const address = socket.address();
assert.notEqual(typeof address, "string");
return address.port;
}
async function waitFor(predicate: () => boolean, description: string): Promise<void> {
const startedAt = Date.now();
while (!predicate()) {
if (Date.now() - startedAt > 1_000) {
throw new Error(`Timed out waiting for ${description}.`);
}
await new Promise((resolve) => setTimeout(resolve, 5));
}
}
test("CultNet secret helpers round-trip encrypted strings and validate sessions", () => {
const serverSecurity = CultNetServerSecurityOptions.development();
const clientSecurity = serverSecurity.toClientOptions();
const nonce = CultNetSecret.newNonce();
const encrypted = CultNetSecret.encryptString("hello", nonce, clientSecurity);
assert.ok(encrypted);
assert.equal(CultNetSecret.decryptString(encrypted, nonce, serverSecurity), "hello");
const token = CultNetSecret.createSessionToken(
"runtime-face",
new Date(Date.now() + 60_000),
serverSecurity,
);
const validated = CultNetSecret.tryValidateSessionToken(token, serverSecurity);
assert.ok(validated);
assert.equal(validated?.userId, "runtime-face");
assert.equal(validated?.sessionVersion, 0);
});
test("CultNet secret helpers validate C# and Python compatible versioned sessions", () => {
const serverSecurity = CultNetServerSecurityOptions.development();
const expires = new Date(Date.now() + 60_000);
const token = CultNetSecret.createSessionToken(
"318fb4b6-ff5e-4c4f-b911-d81807de53a8",
expires,
serverSecurity,
42,
);
const [payload] = token.split(".");
assert.equal(
new TextDecoder().decode(CultNetSecret.fromBase64Url(payload!)),
`318fb4b6ff5e4c4fb911d81807de53a8|${Math.floor(expires.getTime() / 1000)}|42`,
);
const validated = CultNetSecret.tryValidateSessionToken(token, serverSecurity);
assert.ok(validated);
assert.equal(validated?.userId, "318fb4b6ff5e4c4fb911d81807de53a8");
assert.equal(validated?.sessionVersion, 42);
assert.throws(
() => CultNetSecret.createSessionToken("runtime-face", expires, serverSecurity, 1),
/Guid-compatible/,
);
});
test("CultNet secret helpers validate Python-created versioned sessions", () => {
const token = [
"MzE4ZmI0YjZmZjVlNGM0ZmI5MTFkODE4MDdkZTUzYTh8MjA1MTIyMjQwMHw3Nw",
"jRrUiE5Om7NQVKMJP4PkBkLFVLXqNb8Uu9jg4VG13pU",
].join(".");
const validated = CultNetSecret.tryValidateSessionToken(token, CultNetServerSecurityOptions.development());
assert.ok(validated);
assert.equal(validated?.userId, "318fb4b6ff5e4c4fb911d81807de53a8");
assert.equal(validated?.sessionVersion, 77);
});
test("CultNet peer frames and decodes typed messages over a direct pipe", async () => {
const { a, b } = createDuplexPair();
const sender = new CultNetPeer(a, { wireContract: "cultnet.schema.v0" });
const receiver = new CultNetPeer(b, { wireContract: "cultnet.schema.v0" });
const message = await new Promise<ReturnType<typeof parseCultNetMessage>>((resolve, reject) => {
receiver.once("message", resolve);
receiver.once("invalidMessage", reject);
sender.sendHello({
schemaVersion: "cultnet.hello.v0",
runtimeId: "voidbot-main",
runtimeKind: "node-worker",
agentId: "void",
displayName: "Void",
supportedDocumentTypes: ["ghostlight.agent-state"],
transportProfiles: [
{
schemaVersion: "cultnet.transport_profile.v0",
runtimeId: "voidbot-main",
transports: [
{
transportId: "direct-pipe",
protocol: "tcp_framed",
wireContracts: ["cultnet.schema.v0"],
channels: [{ channelId: "schema", delivery: "reliable", ordering: "ordered" }],
},
],
},
],
});
});
assert.equal(message.schemaVersion, "cultnet.hello.v0");
if (message.schemaVersion === "cultnet.hello.v0") {
assert.equal(message.runtimeId, "voidbot-main");
assert.equal(message.agentId, "void");
assert.equal(message.transportProfiles?.[0]?.transports[0]?.protocol, "tcp_framed");
}
sender.close();
receiver.close();
});
test("tcp_framed transport carries raw schema channel payloads with stats", async () => {
const { a, b } = createDuplexPair();
const left = new TcpFramedTransportConnection(a, createTcpFramedTransportProfile("left"));
const right = new TcpFramedTransportConnection(b, createTcpFramedTransportProfile("right"));
const frame = await new Promise<{ channelId: string; payload: Uint8Array }>((resolve, reject) => {
right.once("frame", resolve);
right.once("error", reject);
left.send("schema", Buffer.from("payload", "utf8"));
});
assert.equal(frame.channelId, "schema");
assert.equal(Buffer.from(frame.payload).toString("utf8"), "payload");
assert.equal(left.stats.framesSent, 1);
assert.equal(right.stats.framesReceived, 1);
assert.throws(() => left.send("unreliable", Buffer.alloc(0)), /only supports the schema channel/);
left.close();
right.close();
});
test("rudp packet codec has a deterministic reliable ordered fixture", () => {
const encoded = encodeRudpPacket({
packetType: "data",
connectionId: 0x01020304,
sequence: 0x0000002a,
ack: 0x00000029,
ackMask: 0x80000001,
channelId: "schema",
reliable: true,
ordered: true,
fragmentId: 7,
fragmentIndex: 1,
fragmentCount: 3,
payload: Buffer.from("hello", "utf8"),
});
assert.equal(
Buffer.from(encoded).toString("hex"),
"434e523000030b2a010203040000002a0000002980000001000700010003000000050600736368656d6168656c6c6f",
);
const decoded = decodeRudpPacket(encoded);
assert.equal(decoded.packetType, "data");
assert.equal(decoded.connectionId, 0x01020304);
assert.equal(decoded.sequence, 0x0000002a);
assert.equal(decoded.ack, 0x00000029);
assert.equal(decoded.ackMask, 0x80000001);
assert.equal(decoded.channelId, "schema");
assert.equal(decoded.reliable, true);
assert.equal(decoded.ordered, true);
assert.equal(decoded.sequenced, false);
assert.equal(decoded.fragmentId, 7);
assert.equal(decoded.fragmentIndex, 1);
assert.equal(decoded.fragmentCount, 3);
assert.equal(Buffer.from(decoded.payload ?? []).toString("utf8"), "hello");
});
test("rudp transport profile advertises state and realtime channel semantics", () => {
const profile = createRudpTransportProfile("node-rudp", {
transportId: "public-rudp",
host: "127.0.0.1",
port: 7777,
maxPayloadBytes: 1200,
maxFragmentBytes: 1000,
});
assert.equal(profile.transports[0]?.protocol, "rudp");
assert.equal(profile.transports[0]?.reconnectPolicy?.schemaVersion, "cultnet.reconnect_policy.v0");
assert.equal(profile.transports[0]?.reconnectPolicy?.baseDelayMs, 1_000);
assert.deepEqual(
profile.transports[0]?.channels.map((channel) => [channel.channelId, channel.delivery, channel.ordering]),
[
["schema", "reliable", "ordered"],
["latest", "unreliable", "sequenced"],
["realtime", "unreliable", "unordered"],
],
);
});
test("reconnect policy exposes the shared portable delay contract", () => {
const policy = createCultNetReconnectPolicy({ policyId: "rudp-default", maxAttempts: 8 });
assert.equal(policy.schemaVersion, "cultnet.reconnect_policy.v0");
assert.equal(policy.policyId, "rudp-default");
assert.equal(policy.maxAttempts, 8);
assert.equal(computeCultNetReconnectDelayMs(policy, 1), 1_000);
assert.equal(computeCultNetReconnectDelayMs(policy, 3, 17), 4_017);
assert.equal(computeCultNetReconnectDelayMs(policy, 9, 999), 30_250);
assert.equal(computeCultNetReconnectDelayMs(policy, 0, -5), 1_000);
});
test("reconnect controller schedules attempts and reset with the shared policy", () => {
const policy = createCultNetReconnectPolicy({ maxAttempts: 2 });
const controller = new CultNetReconnectController(policy);
const first = controller.recordFailure(10_000);
assert.deepEqual(first, {
attempt: 1,
shouldRetry: true,
delayMs: 1_000,
nextAttemptAtMs: 11_000,
exhausted: false,
});
assert.equal(controller.canAttempt(10_999), false);
assert.equal(controller.canAttempt(11_000), true);
const second = controller.recordFailure(11_000, 17);
assert.equal(second.attempt, 2);
assert.equal(second.delayMs, 2_017);
assert.equal(second.nextAttemptAtMs, 13_017);
assert.equal(second.shouldRetry, true);
const exhausted = controller.recordFailure(13_017);
assert.deepEqual(exhausted, {
attempt: 2,
shouldRetry: false,
delayMs: 0,
exhausted: true,
});
assert.equal(controller.exhausted, true);
assert.equal(controller.canAttempt(99_000), false);
controller.reset();
assert.equal(controller.attempt, 0);
assert.equal(controller.nextAttemptAtMs, undefined);
assert.equal(controller.exhausted, false);
assert.equal(controller.canAttempt(99_000), true);
});
test("rudp reconnect loop consumes the shared reconnect controller", () => {
let nowMs = 10_000;
let capturedTimer: (() => void) | undefined;
const transports: FakeRudpReconnectTransport[] = [];
const loop = new CultNetRudpReconnectLoop({
reconnectPolicy: createCultNetReconnectPolicy({ maxAttempts: 2 }),
connectPayload: Buffer.from("join", "utf8"),
createTransport: () => {
const transport = new FakeRudpReconnectTransport();
transports.push(transport);
return transport;
},
nowMs: () => nowMs,
jitterMs: () => 17,
setTimer: (callback, delayMs) => {
assert.equal(delayMs, 1_017);
capturedTimer = callback;
return "timer";
},
clearTimer: () => {
capturedTimer = undefined;
},
});
const first = loop.start() as FakeRudpReconnectTransport;
assert.equal(first.connectCalls, 1);
assert.equal(Buffer.from(first.lastPayload ?? []).toString("utf8"), "join");
first.emit("close");
assert.equal(loop.reconnectController.attempt, 1);
assert.equal(loop.reconnectController.nextAttemptAtMs, 11_017);
assert.equal(typeof capturedTimer, "function");
nowMs = 11_017;
capturedTimer?.();
assert.equal(transports.length, 2);
assert.equal(transports[1]?.connectCalls, 1);
loop.markConnected();
assert.equal(loop.reconnectController.attempt, 0);
loop.stop();
assert.equal(transports[1]?.closeCalls, 1);
assert.equal(loop.transport, undefined);
});
test("rudp session handshake acks reliable connect and accept packets", () => {
const client = new CultNetRudpSession({ connectionId: 0x0a0b0c0d, initialSequence: 1, resendDelayMs: 50 });
const server = new CultNetRudpSession({ connectionId: 0x0a0b0c0d, initialSequence: 100, resendDelayMs: 50 });
const connect = client.createConnect(0, Buffer.from("join", "utf8"));
assert.equal(connect.packetType, "connect");
assert.equal(connect.sequence, 1);
assert.deepEqual(client.pendingReliableSequences, [1]);
const accept = server.acceptConnect(connect, 10, Buffer.from("ok", "utf8"));
assert.equal(accept.packetType, "accept");
assert.equal(accept.ack, 1);
assert.equal(server.connected, true);
assert.deepEqual(server.pendingReliableSequences, [100]);
const retransmittedAccept = server.acceptConnect(connect, 15, Buffer.from("ok", "utf8"));
assert.deepEqual(
encodeRudpPacket(retransmittedAccept),
encodeRudpPacket(accept),
"a retransmitted Connect reuses the pending Accept packet",
);
assert.deepEqual(server.pendingReliableSequences, [100]);
client.receive(accept, 20);
assert.equal(client.connected, true);
assert.deepEqual(client.pendingReliableSequences, []);
const ack = client.createAck();
assert.equal(ack.sequence, 0);
assert.equal(ack.ack, 100);
server.receive(ack, 30);
assert.deepEqual(server.pendingReliableSequences, []);
});
test("rudp session computes ack masks and clears pending reliable packets", () => {
const sender = new CultNetRudpSession({ connectionId: 7, initialSequence: 10, resendDelayMs: 100 });
const receiver = new CultNetRudpSession({ connectionId: 7, initialSequence: 200, resendDelayMs: 100 });
sender.receive({ packetType: "accept", connectionId: 7, sequence: 1, ack: 0, ackMask: 0, channelId: "control" });
receiver.receive({ packetType: "accept", connectionId: 7, sequence: 2, ack: 0, ackMask: 0, channelId: "control" });
const first = sender.send("schema", Buffer.from("first"), { reliable: true, ordered: true, nowMs: 0 });
const second = sender.send("schema", Buffer.from("second"), { reliable: true, ordered: true, nowMs: 0 });
const third = sender.send("schema", Buffer.from("third"), { reliable: true, ordered: true, nowMs: 0 });
assert.deepEqual(sender.pendingReliableSequences, [10, 11, 12]);
receiver.receive(first);
receiver.receive(third);
const ackWithGap = receiver.createAck();
assert.equal(ackWithGap.ack, 12);
assert.equal(ackWithGap.ackMask, 0b10 | (1 << 9));
sender.receive(ackWithGap);
assert.deepEqual(sender.pendingReliableSequences, [11]);
receiver.receive(second);
const fullAck = receiver.createAck();
assert.equal(fullAck.ack, 12);
assert.equal(fullAck.ackMask, 0b11 | (1 << 9));
sender.receive(fullAck);
assert.deepEqual(sender.pendingReliableSequences, []);
});
test("rudp session schedules reliable resends until acked", () => {
const session = new CultNetRudpSession({ connectionId: 99, initialSequence: 1, resendDelayMs: 100 });
session.receive({ packetType: "accept", connectionId: 99, sequence: 50, ack: 0, ackMask: 0, channelId: "control" });
const sent = session.send("schema", Buffer.from("payload"), { reliable: true, ordered: true, nowMs: 10 });
assert.deepEqual(session.dueResends(90), []);
assert.deepEqual(session.dueResends(110).map((packet) => packet.sequence), [sent.sequence]);
assert.deepEqual(session.dueResends(150), []);
session.receive({ packetType: "ack", connectionId: 99, sequence: 51, ack: sent.sequence, ackMask: 0, channelId: "control" });
assert.deepEqual(session.dueResends(250), []);
});
test("rudp session pings and detects receive timeout", () => {
const client = new CultNetRudpSession({ connectionId: 101, initialSequence: 1 });
const server = new CultNetRudpSession({ connectionId: 101, initialSequence: 100 });
const connect = client.createConnect(0, Buffer.from("join"));
const accept = server.acceptConnect(connect, 10);
client.receive(accept, 20);
const ping = client.createPing(Buffer.from("pulse"));
const pingResult = server.receive(ping, 30);
assert.equal(pingResult.reply?.packetType, "pong");
assert.deepEqual(Buffer.from(pingResult.reply?.payload ?? []), Buffer.from("pulse"));
const pongResult = client.receive(pingResult.reply!, 40);
assert.equal(pongResult.pong, true);
assert.deepEqual(Buffer.from(pongResult.pongPayload ?? []), Buffer.from("pulse"));
assert.equal(client.checkTimeout(90, 50), false);
assert.equal(client.checkTimeout(91, 50), true);
assert.equal(client.connected, false);
});
test("rudp session bounds pending reliable packets before enqueue", () => {
const session = new CultNetRudpSession({ connectionId: 102, initialSequence: 1, maxPendingReliablePackets: 2 });
session.receive({ packetType: "accept", connectionId: 102, sequence: 50, ack: 0, ackMask: 0, channelId: "control" });
session.send("schema", Buffer.from("first"), { reliable: true, ordered: true });
session.send("schema", Buffer.from("second"), { reliable: true, ordered: true });
assert.throws(
() => session.send("schema", Buffer.from("third"), { reliable: true, ordered: true }),
/reliable send queue is full/,
);
assert.deepEqual(session.pendingReliableSequences, [1, 2]);
const fragmented = new CultNetRudpSession({ connectionId: 103, initialSequence: 1, maxPendingReliablePackets: 3 });
fragmented.receive({ packetType: "accept", connectionId: 103, sequence: 50, ack: 0, ackMask: 0, channelId: "control" });
assert.throws(
() => fragmented.sendMany("schema", Buffer.from("fragment-me"), { reliable: true, ordered: true, maxFragmentBytes: 3 }),
/reliable send queue is full/,
);
assert.deepEqual(fragmented.pendingReliableSequences, []);
});
test("rudp session suppresses duplicates and delivers reliable ordered payloads in sequence", () => {
const sender = new CultNetRudpSession({ connectionId: 123, initialSequence: 1 });
const receiver = new CultNetRudpSession({ connectionId: 123, initialSequence: 100 });
sender.receive({ packetType: "accept", connectionId: 123, sequence: 90, ack: 0, ackMask: 0, channelId: "control" });
receiver.receive({ packetType: "accept", connectionId: 123, sequence: 91, ack: 0, ackMask: 0, channelId: "control" });
const first = sender.send("schema", Buffer.from("first"), { reliable: true, ordered: true });
const second = sender.send("schema", Buffer.from("second"), { reliable: true, ordered: true });
const third = sender.send("schema", Buffer.from("third"), { reliable: true, ordered: true });
assert.deepEqual(receiver.receive(first).delivered.map((frame) => Buffer.from(frame.payload).toString("utf8")), ["first"]);
assert.deepEqual(receiver.receive(third).delivered, []);
assert.deepEqual(receiver.receive(first).delivered, []);
assert.deepEqual(receiver.receive(second).delivered.map((frame) => Buffer.from(frame.payload).toString("utf8")), [
"second",
"third",
]);
});
test("rudp session skips received control packets while ordering schema payloads", () => {
const sender = new CultNetRudpSession({ connectionId: 124, initialSequence: 1 });
const receiver = new CultNetRudpSession({ connectionId: 124, initialSequence: 100 });
sender.receive({ packetType: "accept", connectionId: 124, sequence: 90, ack: 0, ackMask: 0, channelId: "control" });
receiver.receive({ packetType: "accept", connectionId: 124, sequence: 91, ack: 0, ackMask: 0, channelId: "control" });
const first = sender.send("schema", Buffer.from("first"), { reliable: true, ordered: true });
const control = sender.createAck();
const second = sender.send("schema", Buffer.from("second"), { reliable: true, ordered: true });
assert.equal(control.sequence, 0);
assert.equal(second.sequence, first.sequence + 1);
assert.deepEqual(receiver.receive(first).delivered.map((frame) => Buffer.from(frame.payload).toString("utf8")), ["first"]);
assert.deepEqual(receiver.receive(control).delivered, []);
assert.deepEqual(receiver.receive(second).delivered.map((frame) => Buffer.from(frame.payload).toString("utf8")), ["second"]);
});
test("rudp session fragments and reassembles reliable ordered payloads", () => {
const sender = new CultNetRudpSession({ connectionId: 456, initialSequence: 1 });
const receiver = new CultNetRudpSession({ connectionId: 456, initialSequence: 100 });
sender.receive({ packetType: "accept", connectionId: 456, sequence: 90, ack: 0, ackMask: 0, channelId: "control" });
receiver.receive({ packetType: "accept", connectionId: 456, sequence: 91, ack: 0, ackMask: 0, channelId: "control" });
const packets = sender.sendMany("schema", Buffer.from("fragment-me-please"), {
reliable: true,
ordered: true,
nowMs: 10,
maxFragmentBytes: 5,
});
assert.equal(packets.length, 4);
assert.deepEqual(packets.map((packet) => packet.fragmentCount), [4, 4, 4, 4]);
assert.deepEqual(packets.map((packet) => packet.fragmentIndex), [0, 1, 2, 3]);
assert.ok(packets.every((packet) => packet.fragmentId === packets[0]?.fragmentId));
assert.deepEqual(receiver.receive(packets[0]!).delivered, []);
assert.deepEqual(receiver.receive(packets[1]!).delivered, []);
assert.deepEqual(receiver.receive(packets[2]!).delivered, []);
const delivered = receiver.receive(packets[3]!).delivered;
assert.equal(delivered.length, 1);
assert.equal(Buffer.from(delivered[0]!.payload).toString("utf8"), "fragment-me-please");
assert.equal(delivered[0]!.sequence, packets[0]!.sequence);
});
test("rudp socket transport handshakes and carries reliable ordered schema frames over UDP", async () => {
const serverSocket = await bindUdpSocket();
const clientSocket = await bindUdpSocket();
const connectionId = 0x10203040;
const server = new CultNetRudpSocketTransportConnection({
runtimeId: "rudp-server",
socket: serverSocket,
mode: "server",
connectionId,
initialSequence: 100,
resendDelayMs: 25,
resendPollMs: 5,
});
const client = new CultNetRudpSocketTransportConnection({
runtimeId: "rudp-client",
socket: clientSocket,
mode: "client",
remoteHost: "127.0.0.1",
remotePort: udpPort(serverSocket),
connectionId,
initialSequence: 1,
resendDelayMs: 25,
resendPollMs: 5,
});
try {
const serverFrame = new Promise<{ channelId: string; payload: Uint8Array }>((resolve, reject) => {
server.once("frame", resolve);
server.once("error", reject);
});
client.connect(Buffer.from("join", "utf8"));
await waitFor(() => client.connected && server.connected, "RUDP socket handshake");
client.send("schema", Buffer.from("client-state", "utf8"));
const receivedByServer = await serverFrame;
assert.equal(receivedByServer.channelId, "schema");
assert.equal(Buffer.from(receivedByServer.payload).toString("utf8"), "client-state");
const clientFrame = new Promise<{ channelId: string; payload: Uint8Array }>((resolve, reject) => {
client.once("frame", resolve);
client.once("error", reject);
});
server.send("schema", Buffer.from("server-state", "utf8"));
const receivedByClient = await clientFrame;
assert.equal(receivedByClient.channelId, "schema");
assert.equal(Buffer.from(receivedByClient.payload).toString("utf8"), "server-state");
assert.equal(client.stats.framesSent, 1);
assert.equal(server.stats.framesReceived, 1);
assert.equal(server.profile.transports[0]?.protocol, "rudp");
} finally {
client.close();
server.close();
}
});
test("rudp socket transport carries fragmented reliable ordered schema frames over UDP", async () => {
const serverSocket = await bindUdpSocket();
const clientSocket = await bindUdpSocket();
const connectionId = 0x10203041;
const server = new CultNetRudpSocketTransportConnection({
runtimeId: "rudp-fragment-server",
socket: serverSocket,
mode: "server",
connectionId,
initialSequence: 100,
resendDelayMs: 25,
resendPollMs: 5,
maxFragmentBytes: 8,
});
const client = new CultNetRudpSocketTransportConnection({
runtimeId: "rudp-fragment-client",
socket: clientSocket,
mode: "client",
remoteHost: "127.0.0.1",
remotePort: udpPort(serverSocket),
connectionId,
initialSequence: 1,
resendDelayMs: 25,
resendPollMs: 5,
maxFragmentBytes: 8,
});
try {
const payload = Buffer.from("this-schema-frame-is-larger-than-one-rudp-fragment", "utf8");
const serverFrame = new Promise<{ channelId: string; payload: Uint8Array }>((resolve, reject) => {
server.once("frame", resolve);
server.once("error", reject);
});
client.connect(Buffer.from("join", "utf8"));
await waitFor(() => client.connected && server.connected, "fragmented RUDP socket handshake");
client.send("schema", payload);
const receivedByServer = await serverFrame;
assert.equal(receivedByServer.channelId, "schema");
assert.equal(Buffer.from(receivedByServer.payload).toString("utf8"), payload.toString("utf8"));
assert.equal(client.stats.framesSent, 1);
assert.equal(server.stats.framesReceived, 1);
} finally {
client.close();
server.close();
}
});
test("CultNet peer can speak schema messages through the RUDP socket transport", async () => {
const serverSocket = await bindUdpSocket();
const clientSocket = await bindUdpSocket();
const connectionId = 0x50607080;
const serverTransport = new CultNetRudpSocketTransportConnection({
runtimeId: "rudp-peer-server",
socket: serverSocket,
mode: "server",
connectionId,
initialSequence: 500,
resendDelayMs: 25,
resendPollMs: 5,
});
const clientTransport = new CultNetRudpSocketTransportConnection({
runtimeId: "rudp-peer-client",
socket: clientSocket,
mode: "client",
remoteHost: "127.0.0.1",
remotePort: udpPort(serverSocket),
connectionId,
initialSequence: 10,
resendDelayMs: 25,
resendPollMs: 5,
});
try {
const sender = new CultNetPeer(clientTransport, { wireContract: "cultnet.schema.v0" });
const receiver = new CultNetPeer(serverTransport, { wireContract: "cultnet.schema.v0" });
clientTransport.connect();
await waitFor(() => clientTransport.connected && serverTransport.connected, "RUDP peer socket handshake");
const message = await new Promise<ReturnType<typeof parseCultNetMessage>>((resolve, reject) => {
receiver.once("message", resolve);
receiver.once("invalidMessage", reject);
clientTransport.once("error", reject);
serverTransport.once("error", reject);
sender.sendHello({
schemaVersion: "cultnet.hello.v0",
runtimeId: "rudp-peer-client",
runtimeKind: "node-worker",
transportProfiles: [clientTransport.profile],
});
});
assert.equal(message.schemaVersion, "cultnet.hello.v0");
if (message.schemaVersion === "cultnet.hello.v0") {
assert.equal(message.runtimeId, "rudp-peer-client");
assert.equal(message.transportProfiles?.[0]?.transports[0]?.protocol, "rudp");
}
sender.close();
receiver.close();
} finally {
clientTransport.close();
serverTransport.close();
}
});
test("CultNet peer can speak through a transport connection", async () => {
const { a, b } = createDuplexPair();
const leftTransport = new TcpFramedTransportConnection(a, createTcpFramedTransportProfile("left"));
const rightTransport = new TcpFramedTransportConnection(b, createTcpFramedTransportProfile("right"));
const sender = new CultNetPeer(leftTransport, { wireContract: "cultnet.schema.v0" });
const receiver = new CultNetPeer(rightTransport, { wireContract: "cultnet.schema.v0" });
const message = await new Promise<ReturnType<typeof parseCultNetMessage>>((resolve, reject) => {
receiver.once("message", resolve);
receiver.once("invalidMessage", reject);
sender.sendHello({
schemaVersion: "cultnet.hello.v0",
runtimeId: "transport-sender",
runtimeKind: "node-worker",
});
});
assert.equal(message.schemaVersion, "cultnet.hello.v0");
if (message.schemaVersion === "cultnet.hello.v0") {
assert.equal(message.runtimeId, "transport-sender");
}
assert.equal(leftTransport.stats.framesSent, 1);
assert.equal(rightTransport.stats.framesReceived, 1);
sender.close();
receiver.close();
});
test("CultNet TCP helper constructs a transport-backed peer with profile metadata", async () => {
const { a, b } = createDuplexPair();
const sender = createTcpFramedCultNetPeer(a, {
runtimeId: "tcp-helper-left",
wireContract: "cultnet.schema.v0",
transportId: "helper-left",
host: "127.0.0.1",
port: 17777,
maxPayloadBytes: 64 * 1024,
});
const receiver = createTcpFramedCultNetPeer(b, {
runtimeId: "tcp-helper-right",
wireContract: "cultnet.schema.v0",
});
assert.equal(sender.transportProfile?.runtimeId, "tcp-helper-left");
assert.equal(sender.transportProfile?.transports[0]?.transportId, "helper-left");
assert.equal(sender.transportProfile?.transports[0]?.protocol, "tcp_framed");
assert.equal(sender.transportProfile?.transports[0]?.host, "127.0.0.1");
assert.equal(sender.transportProfile?.transports[0]?.port, 17777);
assert.equal(sender.transportProfile?.transports[0]?.channels[0]?.channelId, "schema");
assert.equal(sender.transportProfile?.transports[0]?.channels[0]?.maxPayloadBytes, 64 * 1024);
const message = await new Promise<ReturnType<typeof parseCultNetMessage>>((resolve, reject) => {
receiver.once("message", resolve);
receiver.once("invalidMessage", reject);
sender.sendHello({
schemaVersion: "cultnet.hello.v0",
runtimeId: "tcp-helper-sender",
runtimeKind: "node-worker",
});
});
assert.equal(message.schemaVersion, "cultnet.hello.v0");
if (message.schemaVersion === "cultnet.hello.v0") {
assert.equal(message.runtimeId, "tcp-helper-sender");
}
sender.close();
receiver.close();
});
test("CultNet can round-trip gamecult.networking.v0 auth messages through the explicit legacy contract", () => {
const message: CultNetLoginMessage = {
schemaVersion: "cultnet.login.v0",
nonce: "bm9uY2U",
auth: "YXV0aA",
password: "cGFzc3dvcmQ",
};
const wireValue = encodeCultNetMessageForWire(message, "gamecult.networking.v0");
assert.deepEqual(wireValue, [
0,
[
new TextEncoder().encode("nonce"),
new TextEncoder().encode("auth"),
new TextEncoder().encode("password"),
],
]);
const decoded = parseCultNetMessage(wireValue, "gamecult.networking.v0");
assert.deepEqual(decoded, message);
});
test("CultNet schema discovery catalog can advertise canonical schemas without inline bodies by default", () => {
const response = cultNetBuiltinSchemaRegistry.createCatalogResponse({
schemaVersion: "cultnet.schema_catalog_request.v0",
messageId: "catalog-1",
});
const ghostlight = response.schemas.find((schema) => schema.documentType === "ghostlight.agent-state");
assert.ok(ghostlight);
assert.equal(ghostlight?.kind, "document_payload");
assert.equal(ghostlight?.documentType, "ghostlight.agent-state");
assert.equal(typeof ghostlight?.contentHash, "string");
assert.equal(ghostlight?.schemaJson, undefined);
const transportProfile = response.schemas.find((schema) => schema.schemaVersion === "cultnet.transport_profile.v0");
assert.ok(transportProfile);
assert.equal(transportProfile?.kind, "shared_contract");
assert.equal(transportProfile?.schemaId, cultNetSchemas.transportProfileSchema.$id);
assert.deepEqual(transportProfile?.wireContracts, ["cultnet.schema.v0"]);
const shardCatalogRequest = response.schemas.find((schema) => schema.schemaVersion === "cultnet.shard_catalog_request.v0");
assert.ok(shardCatalogRequest);
assert.equal(shardCatalogRequest?.schemaId, cultNetSchemas.shardCatalogRequestSchema.$id);
assert.deepEqual(shardCatalogRequest?.wireContracts, ["cultnet.schema.v0"]);
const shardCatalogResponse = response.schemas.find((schema) => schema.schemaVersion === "cultnet.shard_catalog_response.v0");
assert.ok(shardCatalogResponse);
assert.equal(shardCatalogResponse?.schemaId, cultNetSchemas.shardCatalogResponseSchema.$id);
assert.deepEqual(shardCatalogResponse?.wireContracts, ["cultnet.schema.v0"]);
assert.equal(
cultNetSchemas.transportProfileSchema.properties.transports.items.properties.reconnectPolicy.properties.schemaVersion.const,
"cultnet.reconnect_policy.v0",
);
});
test("CultNet schema catalog applies remote descriptors and notifies watchers", () => {
const catalog = new CultNetSchemaCatalog();
let watchedSchemaId: string | undefined;
const unsubscribe = catalog.watch((descriptor) => {
watchedSchemaId = descriptor.schemaId;
});
const response = cultNetBuiltinSchemaRegistry.createCatalogResponse({
schemaVersion: "cultnet.schema_catalog_request.v0",
messageId: "catalog-apply",
includeSchemaJson: true,
kinds: ["document_payload"],
});
const applied = catalog.applyResponse(response);
assert.ok(applied.some((descriptor) => descriptor.documentType === "ghostlight.agent-state"));
assert.equal(watchedSchemaId, applied.at(-1)?.schemaId);
assert.equal(catalog.get(applied[0]!.schemaId)?.schemaJson, undefined);
assert.equal(typeof catalog.get(applied[0]!.schemaId, { includeSchemaJson: true })?.schemaJson, "string");
assert.deepEqual(
catalog.list({ kinds: ["document_payload"] }).map((descriptor) => descriptor.kind),
catalog.list().map((descriptor) => descriptor.kind),
);
unsubscribe();
});
test("CultNet peer can request and sync schema catalogs by message id", async () => {
const { a, b } = createDuplexPair();
const requester = createTcpFramedCultNetPeer(a, {
runtimeId: "catalog-requester",
wireContract: "cultnet.schema.v0",
});
const responder = createTcpFramedCultNetPeer(b, {
runtimeId: "catalog-responder",
wireContract: "cultnet.schema.v0",
});
responder.on("message", (message) => {
if (message.schemaVersion === "cultnet.schema_catalog_request.v0") {
responder.sendSchemaCatalogResponse(cultNetBuiltinSchemaRegistry.createCatalogResponse(message));
}
});
const synced = new CultNetSchemaCatalog();
const applied = await requester.syncSchemaCatalog(synced, {
messageId: "peer-schema-catalog",
includeSchemaJson: true,
kinds: ["document_payload"],
timeoutMs: 1_000,
});
assert.ok(applied.some((descriptor) => descriptor.documentType === "ghostlight.agent-state"));
assert.equal(synced.get(applied[0]!.schemaId)?.schemaJson, undefined);
assert.equal(typeof synced.get(applied[0]!.schemaId, { includeSchemaJson: true })?.schemaJson, "string");
requester.close();
responder.close();
});
test("CultNet shard catalog filters descriptors and answers catalog requests", () => {
const catalog = new CultNetShardCatalog();
let watchedShardId: string | undefined;
const unsubscribe = catalog.watch((descriptor) => {
watchedShardId = descriptor.shardId;
});
catalog.upsert({
shardId: "notes-a",
ownerRuntimeId: "ts-owner",
epoch: 7,
isPrimary: true,
schemaIds: ["note.v1"],
keyPrefix: "note:",
primaryEndpoints: ["rudp://127.0.0.1:4100"],
authorityLeaseId: "lease-a",
});
catalog.upsert({
shardId: "profiles-a",
ownerRuntimeId: "ts-owner",
epoch: 3,
schemaIds: ["profile.v1"],
keyPrefix: "profile:",
});
assert.equal(watchedShardId, "profiles-a");
assert.equal(shardServes(catalog.get("notes-a")!, { schemaId: "note.v1", recordKey: "note:1" }), true);
assert.equal(shardServes(catalog.get("notes-a")!, { schemaId: "note", recordKey: "note:1" }), true);
assert.equal(shardServes(catalog.get("notes-a")!, { schemaId: "profile.v1", recordKey: "note:1" }), false);
assert.deepEqual(catalog.list({ schemaIds: ["note.v1"], recordKeys: ["note:1"] }).map((shard) => shard.shardId), ["notes-a"]);
assert.deepEqual(catalog.list({ schemaIds: ["note"], recordKeys: ["note:1"] }).map((shard) => shard.shardId), ["notes-a"]);
const response = catalog.createCatalogResponse({
schemaVersion: "cultnet.shard_catalog_request.v0",
messageId: "shards",
schemaIds: ["note"],
recordKeys: ["note:2"],
});
assert.equal(response.schemaVersion, "cultnet.shard_catalog_response.v0");
assert.equal(response.shards[0]?.shardId, "notes-a");
const parsed = parseCultNetMessage(response);
assert.equal(parsed.schemaVersion, "cultnet.shard_catalog_response.v0");
if (parsed.schemaVersion === "cultnet.shard_catalog_response.v0") {
assert.equal(parsed.shards[0]?.ownerRuntimeId, "ts-owner");
}
unsubscribe();
});
test("CultNet peer can request and sync shard catalogs by message id", async () => {
const { a, b } = createDuplexPair();
const requester = createTcpFramedCultNetPeer(a, {
runtimeId: "shard-requester",
wireContract: "cultnet.schema.v0",
});
const responder = createTcpFramedCultNetPeer(b, {
runtimeId: "shard-responder",
wireContract: "cultnet.schema.v0",
});
const remote = new CultNetShardCatalog();
remote.upsert({
shardId: "notes-peer",
ownerRuntimeId: "shard-responder",
epoch: 1,
isPrimary: true,
schemaIds: ["note.v1"],
keyPrefix: "note:",
primaryEndpoints: ["rudp://127.0.0.1:4200"],
});
responder.on("message", (message) => {
if (message.schemaVersion === "cultnet.shard_catalog_request.v0") {
responder.sendShardCatalogResponse(remote.createCatalogResponse(message));
}
});
const synced = new CultNetShardCatalog();
const applied = await requester.syncShardCatalog(synced, {
messageId: "peer-shards",
schemaIds: ["note"],
recordKeys: ["note:local"],
timeoutMs: 1_000,
});
assert.equal(applied[0]?.shardId, "notes-peer");
assert.equal(synced.get("notes-peer")?.primaryEndpoints?.[0], "rudp://127.0.0.1:4200");
requester.close();
responder.close();
});
test("CultNet schema discovery can round-trip over the legacy wire contract when schemas are requested inline", () => {
const registry = new CultNetSchemaRegistry([
{
schemaId: "https://example.test/contracts/example.schema.json",
kind: "shared_contract",
schema: {
$schema: "https://json-schema.org/draft/2020-12/schema",
$id: "https://example.test/contracts/example.schema.json",
type: "object",
properties: {
value: { type: "string" },
},
required: ["value"],
additionalProperties: false,
},
title: "Example Schema",
wireContracts: ["cultnet.schema.v0", "gamecult.networking.v0"],
},
]);
const response = registry.createCatalogResponse({
schemaVersion: "cultnet.schema_catalog_request.v0",
messageId: "catalog-legacy",
includeSchemaJson: true,
});
const wireValue = encodeCultNetMessageForWire(response, "gamecult.networking.v0");
const decoded = parseCultNetMessage(wireValue, "gamecult.networking.v0");
assert.equal(decoded.schemaVersion, "cultnet.schema_catalog_response.v0");
if (decoded.schemaVersion === "cultnet.schema_catalog_response.v0") {
assert.equal(decoded.messageId, "catalog-legacy");
assert.equal(decoded.schemas[0]?.schemaId, "https://example.test/contracts/example.schema.json");
assert.match(decoded.schemas[0]?.schemaJson ?? "", /"value"/u);
}
});
test("CultNet document registry builds snapshots and applies document puts through CultCache", async () => {
const tempDir = mkdtempSync(join(tmpdir(), "cultnetts-"));
try {
const documentDefinition = defineDocumentType({
type: "ghostlight.agent-state",
schemaId: cultNetSchemas.ghostlightAgentStateSchema.$id,
schemaName: "ghostlight.agent-state",
schemaVersion: "ghostlight.agent_state.v0",
schema: z.custom<GhostlightAgentStateDocument>((value) => {
try {
validateGhostlightAgentState(value);
return true;
} catch {
return false;
}
}),
});
const registry = new CultNetDocumentRegistry([
defineCultNetDocumentBinding({
definition: documentDefinition,
payloadSchemaVersion: "ghostlight.agent_state.v0",
}),
]);
const originStore = new SingleFileMessagePackBackingStore(join(tempDir, "origin.msgpack"));
const targetStore = new SingleFileMessagePackBackingStore(join(tempDir, "target.msgpack"));
const originCache = CultCache.builder()
.withDocumentType(documentDefinition)
.withGenericStore(originStore)
.build();
const targetCache = CultCache.builder()
.withDocumentType(documentDefinition)
.withGenericStore(targetStore)
.build();
const payload = validateGhostlightAgentState({
schema_version: "ghostlight.agent_state.v0",
world: {
world_id: "epiphany-face",
setting: "test harness",
time: { label: "now" },
canon_context: ["test"],
},
agents: [
{
agent_id: "epiphany.persona",
identity: {
name: "Persona",
roles: ["public-surface"],
origin: "test",
public_description: "test",
},
canonical_state: {
underlying_organization: {},
stable_dispositions: {},
behavioral_dimensions: {},
presentation_strategy: {},
voice_style: {},
situational_state: {},
values: [],
},
goals: [],
memories: {
episodic: [],
semantic: [],
relationship_summaries: [],
},
perceived_state_overlays: [],
},
],
relationships: [],
events: [],
scenes: [],
});
await originCache.put(documentDefinition, "epiphany.persona", payload);
const snapshot = registry.createSnapshotResponse(originCache, "snapshot-1");
await registry.applySnapshotResponse(targetCache, snapshot);
const roundTrip = targetCache.get(documentDefinition, "epiphany.persona");
assert.ok(roundTrip);
assert.equal(roundTrip?.schema_version, "ghostlight.agent_state.v0");
assert.equal(roundTrip?.agents[0]?.agent_id, "epiphany.persona");
} finally {
rmSync(tempDir, { recursive: true, force: true });
}
});
test("CultNet raw replication preserves CultCache payload bytes for bit-compatible neighbors", async () => {
const tempDir = mkdtempSync(join(tmpdir(), "cultnetts-raw-"));
try {
const documentDefinition = defineDocumentType({
type: "ghostlight.agent-state",
schemaId: cultNetSchemas.ghostlightAgentStateSchema.$id,
schemaName: "ghostlight.agent-state",
schemaVersion: "ghostlight.agent_state.v0",
schema: z.custom<GhostlightAgentStateDocument>((value) => {
try {
validateGhostlightAgentState(value);
return true;
} catch {
return false;
}
}),
});
const registry = new CultNetDocumentRegistry([
defineCultNetDocumentBinding({
definition: documentDefinition,
payloadSchemaVersion: "ghostlight.agent_state.v0",
}),
]);
const originCache = CultCache.builder()
.withDocumentType(documentDefinition)
.withGenericStore(new SingleFileMessagePackBackingStore(join(tempDir, "origin.msgpack")))
.build();
const targetCache = CultCache.builder()
.withDocumentType(documentDefinition)
.withGenericStore(new SingleFileMessagePackBackingStore(join(tempDir, "target.msgpack")))
.build();
const payload = validateGhostlightAgentState({
schema_version: "ghostlight.agent_state.v0",
world: {
world_id: "epiphany-face",
setting: "test harness",
time: { label: "now" },
canon_context: ["test"],
},
agents: [
{
agent_id: "epiphany.persona",
identity: {
name: "Persona",
roles: ["public-surface"],
origin: "test",
public_description: "test",
},
canonical_state: {
underlying_organization: {},
stable_dispositions: {},
behavioral_dimensions: {},
presentation_strategy: {},
voice_style: {},
situational_state: {},
values: [],
},
goals: [],
memories: {
episodic: [],
semantic: [],
relationship_summaries: [],
},
perceived_state_overlays: [],
},
],
relationships: [],
events: [],
scenes: [],
});
await originCache.put(documentDefinition, "epiphany.persona", payload);
const rawSnapshot = registry.createRawSnapshotResponse(originCache, "raw-snapshot-1");
assert.equal(rawSnapshot.documents[0]?.schemaId, cultNetSchemas.ghostlightAgentStateSchema.$id);
assert.equal(rawSnapshot.documents[0]?.recordKey, "epiphany.persona");
await registry.applyRawSnapshotResponse(targetCache, rawSnapshot);
const sourceEnvelope = originCache.getRequiredEnvelope(documentDefinition, "epiphany.persona");
const targetEnvelope = targetCache.getRequiredEnvelope(documentDefinition, "epiphany.persona");
assert.deepEqual(targetEnvelope.payload, sourceEnvelope.payload);
assert.equal(targetCache.getRequired(documentDefinition, "epiphany.persona").schema_version, "ghostlight.agent_state.v0");
} finally {
rmSync(tempDir, { recursive: true, force: true });
}
});
test("operation envelopes preserve typed service routing and payload correlation", () => {
const request = parseCultNetMessage({
schemaVersion: "cultnet.operation_request.v0",
messageId: "plugin-42",
serviceId: "sai.vn",
operation: "project",
payloadSchema: "gamecult.eve.plugin_abi.request.v1",
payloadEncoding: "messagepack-base64",
payload: "gaZzY2hlbWHEJ2dhbWVjdWx0LmV2ZS5wbHVnaW5fYWJpLnJlcXVlc3QudjE=",
sourceRuntimeId: "eve-unity",
});
assert.equal(request.schemaVersion, "cultnet.operation_request.v0");
assert.equal(request.messageId, "plugin-42");
assert.equal(request.serviceId, "sai.vn");
const response = parseCultNetMessage({
schemaVersion: "cultnet.operation_response.v0",
messageId: "plugin-42",
serviceId: "sai.vn",
operation: "project",
status: "ok",
payloadSchema: "gamecult.eve.plugin_abi.response.v1",
payloadEncoding: "messagepack-base64",
payload: "gaZzdGF0dXOkb2s=",
diagnostics: [],
});
assert.equal(response.schemaVersion, "cultnet.operation_response.v0");
assert.equal(response.messageId, request.messageId);
});
test("CultNet contracts encode legacy bytes without Node Buffer authority", () => {
const originalBuffer = globalThis.Buffer;
try {
Object.defineProperty(globalThis, "Buffer", { configurable: true, value: undefined });
const message = parseCultNetMessage({
schemaVersion: "cultnet.login.v0",
nonce: "AQID",
auth: "BAUG",
password: "BwgJ",
});
const wire = encodeCultNetMessageForWire(message, "gamecult.networking.v0") as [number, Uint8Array[]];
assert.equal(wire[0], 0);
assert.deepEqual([...wire[1][0]], [1, 2, 3]);
} finally {
Object.defineProperty(globalThis, "Buffer", { configurable: true, value: originalBuffer });
}
});
test("database subscription contracts match the C# live document lane", () => {
const subscribe = parseCultNetMessage({
schemaVersion: "cultnet.database_subscribe.v0",
messageId: "subscribe-counter",
subscriptionId: "counter:browser-1",
schemaIds: ["sample.counter_state.v1"],
recordKeys: ["counter:main"],
includeSnapshot: true,
consumerRuntimeId: "browser-1",
});
assert.equal(subscribe.schemaVersion, "cultnet.database_subscribe.v0");
assert.equal(subscribe.subscriptionId, "counter:browser-1");
const added = parseCultNetMessage({
schemaVersion: "cultnet.database_change_raw.v0",
messageId: "change-counter-1",
subscriptionId: "counter:browser-1",
changeKind: "added",
document: {
schemaId: "sample.counter_state.v1",
recordKey: "counter:main",
storedAt: "2026-08-17T00:00:00Z",
payloadEncoding: "messagepack",
payload: new Uint8Array([0x81, 0xa5, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x01]),
},
});
assert.equal(added.schemaVersion, "cultnet.database_change_raw.v0");
assert.equal(added.document?.recordKey, "counter:main");
const removed = parseCultNetMessage({
schemaVersion: "cultnet.database_change_raw.v0",
messageId: "change-counter-2",
subscriptionId: "counter:browser-1",
changeKind: "removed",
recordKey: "counter:main",
schemaId: "sample.counter_state.v1",
});
assert.equal(removed.schemaVersion, "cultnet.database_change_raw.v0");
assert.equal(removed.recordKey, "counter:main");
const unsubscribe = parseCultNetMessage({
schemaVersion: "cultnet.database_unsubscribe.v0",
messageId: "unsubscribe-counter",
subscriptionId: "counter:browser-1",
});
assert.equal(unsubscribe.schemaVersion, "cultnet.database_unsubscribe.v0");
assert.throws(
() => parseCultNetMessage({
schemaVersion: "cultnet.database_change_raw.v0",
messageId: "invalid-change",
subscriptionId: "counter:browser-1",
changeKind: "updated",
}),
/document: is required/,
);
});
test("RUDP operation service correlates typed payload envelopes", async () => {
const server = await startCultNetOperationServer({
runtimeId: "sai-sidecar",
handler: request => ({
schemaVersion: "cultnet.operation_response.v0",
messageId: request.messageId,
serviceId: request.serviceId,
operation: request.operation,
status: "ok",
payloadSchema: "gamecult.eve.plugin_abi.response.v1",
payloadEncoding: "messagepack-base64",
payload: request.payload,
diagnostics: [],
sourceRuntimeId: "sai-sidecar",
}),
});
try {
const response = await invokeCultNetOperation(server.endpoint, {
schemaVersion: "cultnet.operation_request.v0",
messageId: "service-1",
serviceId: "sai.vn",
operation: "describe",
payloadSchema: "gamecult.eve.plugin_abi.request.v1",
payloadEncoding: "messagepack-base64",
payload: "gaZzY2hlbWHEJ2dhbWVjdWx0LmV2ZS5wbHVnaW5fYWJpLnJlcXVlc3QudjE=",
}, { runtimeId: "eve-test" });
assert.equal(response.messageId, "service-1");
assert.equal(response.serviceId, "sai.vn");
assert.equal(response.status, "ok");
} finally {
await server.close();
}
});
test("rudp sequence-neutral acknowledgements interoperate with ordered receivers", () => {
const sender = new CultNetRudpSession({ connectionId: 125, initialSequence: 1 });
const receiver = new CultNetRudpSession({ connectionId: 125, initialSequence: 100 });
sender.receive({ packetType: "accept", connectionId: 125, sequence: 90, ack: 0, ackMask: 0, channelId: "control" });
receiver.receive({ packetType: "accept", connectionId: 125, sequence: 91, ack: 0, ackMask: 0, channelId: "control" });
const ack = sender.createAck();
const request = sender.send("schema", Buffer.from("snapshot"), { reliable: true, ordered: true });
assert.equal(ack.sequence, 0);
assert.equal(request.sequence, 1);
assert.deepEqual(receiver.receive(ack).delivered, []);
assert.deepEqual(receiver.receive(request).delivered.map(frame => Buffer.from(frame.payload).toString("utf8")), ["snapshot"]);
});
test("CultNet raw replication applies compatible foreign-schema snapshots", async () => {
const tempDir = mkdtempSync(join(tmpdir(), "cultnetts-foreign-schema-raw-"));
try {
const documentDefinition = defineDocumentType({
type: "cultnet.note",
schemaId: "cultnet.note.v1",
schemaName: "cultnet.note",
schemaVersion: "cultnet.note.v1",
schema: z.object({
schema_version: z.string(),
noteId: z.string(),
body: z.string(),
}),
name: "noteId",
});
const registry = new CultNetDocumentRegistry([
defineCultNetDocumentBinding({ definition: documentDefinition }),
]);
const originCache = CultCache.builder()
.withDocumentType(documentDefinition)
.withGenericStore(new SingleFileMessagePackBackingStore(join(tempDir, "origin.msgpack")))
.build();
const targetCache = CultCache.builder()
.withDocumentType(documentDefinition)
.withGenericStore(new SingleFileMessagePackBackingStore(join(tempDir, "target.msgpack")))
.build();
await originCache.put(documentDefinition, "note:foreign-schema", {
schema_version: "cultnet.note.v1",
noteId: "note:foreign-schema",
body: "accepted by payload shape",
});
const rawSnapshot = registry.createRawSnapshotResponse(originCache, "foreign-schema-raw");
rawSnapshot.documents[0]!.schemaId = "runtime.generated.cultnet.note.ui.99";
await registry.applyRawSnapshotResponse(targetCache, rawSnapshot);
assert.equal(
targetCache.getRequired(documentDefinition, "note:foreign-schema").body,
"accepted by payload shape",
);
assert.equal(
targetCache.getRequiredEnvelope(documentDefinition, "note:foreign-schema").schemaId,
"cultnet.note.v1",
);
} finally {
rmSync(tempDir, { recursive: true, force: true });
}
});
test("CultNet document registry filters snapshots by schema aliases", async () => {
const tempDir = mkdtempSync(join(tmpdir(), "cultnetts-alias-snapshot-"));
try {
const documentDefinition = defineDocumentType({
type: "cultnet.alias_note",
schemaId: "sha256:cultnet-alias-note",
schemaName: "cultnet.alias_note",
schemaVersion: "cultnet.alias_note.v1",
schema: z.object({
schema_version: z.string(),
noteId: z.string(),
body: z.string(),
}),
name: "noteId",
});
const registry = new CultNetDocumentRegistry([
defineCultNetDocumentBinding({ definition: documentDefinition }),
]);
const cache = CultCache.builder()
.withDocumentType(documentDefinition)
.withGenericStore(new SingleFileMessagePackBackingStore(join(tempDir, "alias.msgpack")))
.build();
await cache.put(documentDefinition, "note:alias", {
schema_version: "cultnet.alias_note.v1",
noteId: "note:alias",
body: "filtered by alias",
});
const typedSnapshot = registry.createSnapshotResponse(cache, "typed-alias", {
schemaVersion: "cultnet.snapshot_request.v0",
messageId: "typed-alias",
schemaIds: ["cultnet.alias_note.v1"],
});
const rawSnapshot = registry.createRawSnapshotResponse(cache, "raw-alias", {
schemaVersion: "cultnet.snapshot_request.v0",
messageId: "raw-alias",
schemaIds: ["cultnet.alias_note.v1"],
});
assert.equal(typedSnapshot.documents[0]?.schemaId, "sha256:cultnet-alias-note");
assert.equal(typedSnapshot.documents[0]?.recordKey, "note:alias");
assert.equal(rawSnapshot.documents[0]?.schemaId, "sha256:cultnet-alias-note");
assert.equal(rawSnapshot.documents[0]?.recordKey, "note:alias");
} finally {
rmSync(tempDir, { recursive: true, force: true });
}
});
test("CultNet document registry applies typed put and delete messages by schema alias", async () => {
const tempDir = mkdtempSync(join(tmpdir(), "cultnetts-alias-typed-"));
try {
const documentDefinition = defineDocumentType({
type: "cultnet.typed_alias_note",
schemaId: "sha256:cultnet-typed-alias-note",
schemaName: "cultnet.typed_alias_note",
schemaVersion: "cultnet.typed_alias_note.v1",
schema: z.object({
schema_version: z.string(),
noteId: z.string(),
body: z.string(),
}),
name: "noteId",
});
const registry = new CultNetDocumentRegistry([
defineCultNetDocumentBinding({ definition: documentDefinition }),
]);
const cache = CultCache.builder()
.withDocumentType(documentDefinition)
.withGenericStore(new SingleFileMessagePackBackingStore(join(tempDir, "typed-alias.msgpack")))
.build();
await registry.applyDocumentPutMessage(cache, {
schemaVersion: "cultnet.document_put.v0",
messageId: "typed-alias-put",
document: {
schemaId: "cultnet.typed_alias_note.v1",
recordKey: "note:typed-alias",
storedAt: "2026-06-27T00:00:00.000Z",
payload: {
schema_version: "cultnet.typed_alias_note.v1",
noteId: "note:typed-alias",
body: "typed alias applied",
},
},
});
assert.equal(
cache.getRequired(documentDefinition, "note:typed-alias").body,
"typed alias applied",
);
assert.equal(registry.getBySchemaId("cultnet.typed_alias_note.v1")?.definition.type, documentDefinition.type);
assert.equal(await registry.applyDocumentDeleteMessage(cache, {
schemaVersion: "cultnet.document_delete.v0",
messageId: "typed-alias-delete",
schemaId: "cultnet.typed_alias_note.v1",
recordKey: "note:typed-alias",
}), true);
assert.equal(cache.get(documentDefinition, "note:typed-alias"), undefined);
} finally {
rmSync(tempDir, { recursive: true, force: true });
}
});
test("CultNet interop slot compatibility defaults missing trailing fields and rejects mismatched slots", () => {
const note: InteropNote = {
schemaVersion: INTEROP_SCHEMA_VERSION,
documentId: "note:compat",
authorRuntimeId: "compat-peer",
title: "Compatibility",
body: "Missing trailing fields are allowed when declared defaults cover them.",
tags: ["compat"],
};
assert.deepEqual(createInteropFormatter().decode(createLegacyInteropNoteFormatter().encode(note)), {
...note,
tags: [],
});
assert.throws(
() => createInteropFormatter().decode(createMismatchedInteropNoteFormatter().encode(note)),
/Expected string/u,
);
});
test("Ghostlight contract mirror rejects nested payloads that violate the canonical schema", () => {
assert.throws(
() => validateGhostlightAgentState({
schema_version: "ghostlight.agent_state.v0",
world: {
world_id: "ghostlight-lab",
setting: "test",
time: { label: "now" },
canon_context: ["test"],
},
agents: [
{
identity: {
name: "Persona",
roles: ["public-surface"],
origin: "test",
public_description: "test",
},
canonical_state: {
underlying_organization: {},
stable_dispositions: {},
behavioral_dimensions: {},
presentation_strategy: {},
voice_style: {},
situational_state: {},
values: [],
},
goals: [],
memories: {
episodic: [],
semantic: [],
relationship_summaries: [],
},
perceived_state_overlays: [],
},
],
relationships: [],
events: [],
scenes: [],
}),
/agent_id/u,
);
});
test("Generated Ghostlight contracts can feed CultCacheTS directly without a Zod mirror", async () => {
const tempDir = mkdtempSync(join(tmpdir(), "cultnetts-generated-"));
try {
const documentDefinition = defineDocumentType({
type: "ghostlight.agent-state.generated",
schema: ghostlightAgentStateGeneratedContract,
global: true,
});
const store = new SingleFileMessagePackBackingStore(join(tempDir, "generated.msgpack"));
const cache = CultCache.builder()
.withDocumentType(documentDefinition)
.withGenericStore(store)
.build();
const payload: GhostlightAgentStateShape = {
schema_version: "ghostlight.agent_state.v0",
world: {
world_id: "ghostlight-lab",
setting: "test harness",
time: { label: "now" },
canon_context: ["test"],
},
agents: [
{
agent_id: "void",
identity: {
name: "Void",
roles: ["observer"],
origin: "test",
public_description: "test",
},
canonical_state: {
underlying_organization: {},
stable_dispositions: {},
behavioral_dimensions: {},
presentation_strategy: {},
voice_style: {},
situational_state: {},
values: [],
},
goals: [],
memories: {
episodic: [],
semantic: [],
relationship_summaries: [],
},
perceived_state_overlays: [],
},
],
relationships: [],
events: [],
scenes: [],
};
await cache.putGlobal(documentDefinition, payload);
const roundTrip = cache.getRequiredGlobal(documentDefinition);
assert.equal(validateGhostlightAgentStateGenerated(roundTrip), true);
assert.equal(roundTrip.schema_version, "ghostlight.agent_state.v0");
assert.equal(roundTrip.agents[0]?.agent_id, "void");
} finally {
rmSync(tempDir, { recursive: true, force: true });
}
});