Bind runtime presence to route challenges

This commit is contained in:
Meta Vens 2026-09-28 03:54:21 +02:00
commit 542ddd3e58
2 changed files with 36 additions and 11 deletions

View file

@ -13,7 +13,7 @@ import {
encodeRuntimePresenceHealth,
type RuntimePresenceHealth,
} from "./runtime-presence-health";
import { encodeCultNetMessageForWire, parseCultNetMessage, type CultNetRawDocumentRecord } from "./contracts";
import { encodeCultNetMessageForWire, parseCultNetMessage, type CultNetRawDocumentRecord, type CultNetSnapshotRequestMessage } from "./contracts";
import { CultNetRudpSession, decodeRudpPacket, encodeRudpPacket } from "./rudp";
import type { CultNetRudpPacket } from "./rudp";
import dgram from "node:dgram";
@ -80,6 +80,7 @@ export type IdunnRuntimePresencePublisher = {
readonly runtimeInstanceId: string;
readonly requiresWriteLease: boolean;
latestPresenceDocument(): CultNetRawDocumentRecord | null;
publishRouteObservation(request: CultNetSnapshotRequestMessage): Promise<CultNetRawDocumentRecord>;
publish(state: RuntimePresenceHealth["state"], detail: string): Promise<string>;
waitForWriteLease(options?: { pollIntervalMs?: number; signal?: AbortSignal }): Promise<string>;
assertWriteLease(): Promise<string>;
@ -268,17 +269,32 @@ export function createIdunnRuntimePresencePublisher(
return signed.canonicalSha256;
};
const copyLatestPresenceDocument = (): CultNetRawDocumentRecord | null => {
if (!latestPresenceDocument) return null;
return {
...latestPresenceDocument,
payload: new Uint8Array(latestPresenceDocument.payload),
...(latestPresenceDocument.tags ? { tags: [...latestPresenceDocument.tags] } : {}),
};
};
return {
runtimeId: expected.runtimeId,
runtimeInstanceId: options.authority.activation.runtimeInstanceId,
requiresWriteLease: expected.writeLeaseRequired,
latestPresenceDocument() {
if (!latestPresenceDocument) return null;
return {
...latestPresenceDocument,
payload: new Uint8Array(latestPresenceDocument.payload),
...(latestPresenceDocument.tags ? { tags: [...latestPresenceDocument.tags] } : {}),
};
latestPresenceDocument: copyLatestPresenceDocument,
async publishRouteObservation(request) {
if (!request.messageId || request.messageId.trim() !== request.messageId) throw new Error("Idunn route observation requires a message id.");
if ((request.schemaIds && !request.schemaIds.includes(GAMECULT_RUNTIME_PRESENCE_HEALTH_SCHEMA))
|| (request.recordKeys && !request.recordKeys.includes(expected.target))
|| request.shardId !== undefined
|| request.shardEpoch !== undefined) {
throw new Error("Idunn route observation does not request this runtime presence document.");
}
await publish("active", `route-observation:${request.messageId}`);
const document = copyLatestPresenceDocument();
if (!document) throw new Error("Idunn route observation was published without a presence document.");
return document;
},
publish,
async waitForWriteLease({ pollIntervalMs = 5000, signal } = {}) {

View file

@ -19,6 +19,7 @@ import {
runtimePresenceActivationSigningMessage,
runtimePresenceProofPayload,
runtimePresenceProviderSigningMessage,
RUNTIME_PRESENCE_SLOT,
} from "../src/runtime-presence-health";
const providerIdentityContext = "gamecult-provider-health-identity-v1";
@ -53,7 +54,7 @@ test("opens Idunn identity and publishes valid CultNet data while surfacing pigg
"idunn.expected_incarnation.v2", target, `sha256-${"1".repeat(64)}`, "incarnation-1",
`sha256-${"2".repeat(64)}`, "https://github.com/GameCult/StreamPixels.git", "a".repeat(40),
`sha256-${"3".repeat(64)}`, "streampixels-service-yggdrasil", providerIdentity, contract,
`sha256-${"4".repeat(64)}`, "service-boundary-v1", `sha256-${"5".repeat(64)}`, true,
`sha256-${"4".repeat(64)}`, "service-boundary-v1", `sha256-${"5".repeat(64)}`, false,
["streampixels-service-http", "http", "http://127.0.0.1:8831", candidate],
[["streampixels.service.api", "streampixels.api.v1", "v1", 1]],
[["shared-infrastructure", "odin.verse-rendezvous", "odin.verse-topology.v1", "v1", 1, "before-promotion", null, null, null, "rudp://127.0.0.1:17871"]],
@ -101,7 +102,7 @@ test("opens Idunn identity and publishes valid CultNet data while surfacing pigg
});
process.env.GAMECULT_IDUNN_RUNTIME_BUNDLE = bundle;
process.env.GAMECULT_IDUNN_CANDIDATE_BIND = candidate;
process.env.GAMECULT_IDUNN_PROCESS_WRITE_LEASE = path.join(directory, "lease.cc");
delete process.env.GAMECULT_IDUNN_PROCESS_WRITE_LEASE;
process.env.LISTEN_PID = String(process.pid);
process.env.LISTEN_FDS = "2";
process.env.LISTEN_FDNAMES = "gamecult-idunn-runtime-activation-key:gamecult-runtime-presence-identity";
@ -195,12 +196,20 @@ test("opens Idunn identity and publishes valid CultNet data while surfacing pigg
rejectOdinAdmission = false;
await publisher.publish("warming", "accepted presence");
const snapshotDocument = await publisher.publishRouteObservation({
schemaVersion: "cultnet.snapshot_request.v0",
messageId: "route-challenge-1",
schemaIds: ["gamecult.runtime_presence_health.v2"],
recordKeys: [target],
});
const publishedDocument = (receivedMessage as { document: { payload: Uint8Array; schemaId: string; recordKey: string } }).document;
const snapshotDocument = publisher.latestPresenceDocument();
assert.ok(snapshotDocument);
assert.equal(snapshotDocument.schemaId, publishedDocument.schemaId);
assert.equal(snapshotDocument.recordKey, publishedDocument.recordKey);
assert.deepEqual(Buffer.from(snapshotDocument.payload), Buffer.from(publishedDocument.payload));
const routePresence = decode(snapshotDocument.payload) as unknown[];
assert.equal(routePresence[RUNTIME_PRESENCE_SLOT.state], "active");
assert.equal(routePresence[RUNTIME_PRESENCE_SLOT.detail], "route-observation:route-challenge-1");
snapshotDocument.payload[0] = snapshotDocument.payload[0]! ^ 0xff;
assert.deepEqual(Buffer.from(publisher.latestPresenceDocument()?.payload ?? []), Buffer.from(publishedDocument.payload), "snapshot readers cannot mutate publisher state");