fix: validate Kafka refresh delivery in web probe

This commit is contained in:
Codex
2026-07-11 06:59:43 +02:00
parent 5afde90f00
commit 0fa47e9295
10 changed files with 360 additions and 29 deletions
+27 -1
View File
@@ -192,6 +192,15 @@ export interface HwlabRuntimeWebProbeRealtimeFanoutProfileSpec {
readonly navigationMaxAttempts: number;
readonly navigationRetryDelayMs: number;
readonly reconnectQuietMs: number;
readonly expectedProductSse: Readonly<{
deliverySemantics: string;
liveOnly: boolean;
replay: boolean;
replaySupported: boolean;
lossPossible: boolean;
refreshHandoff: boolean;
replayPriorTraceOnReconnect: boolean;
}>;
readonly forbiddenRequestPaths: readonly string[];
readonly requiredEventTypes: Readonly<{
agentrun: readonly string[];
@@ -1435,7 +1444,23 @@ function webProbeRealtimeFanoutProfileConfig(value: unknown, path: string): Hwla
throw new Error(`${path}.debugStreams must contain stdio, agentrun, and hwlab exactly once`);
}
const fromBeginning = booleanField(raw, "fromBeginning", path);
if (fromBeginning !== false) throw new Error(`${path}.fromBeginning must be false for live-only validation`);
if (fromBeginning !== false) throw new Error(`${path}.fromBeginning must be false for turn-scoped debug streams`);
const expectedProductSseRaw = asRecord(raw.expectedProductSse, `${path}.expectedProductSse`);
const expectedProductSse = {
deliverySemantics: stringField(expectedProductSseRaw, "deliverySemantics", `${path}.expectedProductSse`),
liveOnly: booleanField(expectedProductSseRaw, "liveOnly", `${path}.expectedProductSse`),
replay: booleanField(expectedProductSseRaw, "replay", `${path}.expectedProductSse`),
replaySupported: booleanField(expectedProductSseRaw, "replaySupported", `${path}.expectedProductSse`),
lossPossible: booleanField(expectedProductSseRaw, "lossPossible", `${path}.expectedProductSse`),
refreshHandoff: booleanField(expectedProductSseRaw, "refreshHandoff", `${path}.expectedProductSse`),
replayPriorTraceOnReconnect: booleanField(expectedProductSseRaw, "replayPriorTraceOnReconnect", `${path}.expectedProductSse`),
};
if (expectedProductSse.refreshHandoff && (!expectedProductSse.replay || !expectedProductSse.replaySupported || expectedProductSse.liveOnly)) {
throw new Error(`${path}.expectedProductSse refresh handoff requires replay=true, replaySupported=true, and liveOnly=false`);
}
if (expectedProductSse.replayPriorTraceOnReconnect && !expectedProductSse.replay) {
throw new Error(`${path}.expectedProductSse replayPriorTraceOnReconnect requires replay=true`);
}
const requiredEventTypes = asRecord(raw.requiredEventTypes, `${path}.requiredEventTypes`);
const forbiddenRequestPaths = nonEmptyStringArrayField(raw, "forbiddenRequestPaths", path);
if (new Set(forbiddenRequestPaths).size !== forbiddenRequestPaths.length) throw new Error(`${path}.forbiddenRequestPaths must not contain duplicates`);
@@ -1466,6 +1491,7 @@ function webProbeRealtimeFanoutProfileConfig(value: unknown, path: string): Hwla
navigationMaxAttempts: boundedIntegerField(raw, "navigationMaxAttempts", path, 1, 10),
navigationRetryDelayMs: boundedIntegerField(raw, "navigationRetryDelayMs", path, 100, 10_000),
reconnectQuietMs: boundedIntegerField(raw, "reconnectQuietMs", path, 250, 30_000),
expectedProductSse,
forbiddenRequestPaths,
requiredEventTypes: {
agentrun: agentrunEventTypes,