test: isolate stateful error boundary fixtures

This commit is contained in:
diegosouzapw
2026-09-02 08:11:09 -03:00
parent 51b8753703
commit dc66426462
24 changed files with 1505 additions and 1593 deletions

View File

@@ -15,22 +15,9 @@
* pass-through here — the test pins the formatting logic, not PII behaviour.
*/
import { after, describe, it } from "node:test";
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-calllogs-format-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const core = await import("../../src/lib/db/core.ts");
const {
import {
asRecord,
toNumber,
toStringOrNull,
@@ -39,16 +26,7 @@ const {
normalizeDetailState,
toStoredErrorSummary,
buildRequestSummary,
} = await import("../../src/lib/usage/callLogs/format.ts");
after(() => {
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
} from "../../src/lib/usage/callLogs/format.ts";
describe("callLogs/format — coercers", () => {
it("asRecord keeps plain objects, rejects arrays/primitives/null", () => {

View File

@@ -6,30 +6,11 @@
// the string-code extraction.
import { test } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-stream-error-result-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const core = await import("../../src/lib/db/core.ts");
const { isSemaphoreCapacityError, createStreamingErrorResult, getUpstreamErrorIdentifier } =
await import("../../open-sse/handlers/chatCore/streamErrorResult.ts");
test.after(() => {
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
import {
isSemaphoreCapacityError,
createStreamingErrorResult,
getUpstreamErrorIdentifier,
} from "../../open-sse/handlers/chatCore/streamErrorResult.ts";
test("isSemaphoreCapacityError matches the two semaphore codes only", () => {
assert.equal(isSemaphoreCapacityError({ code: "SEMAPHORE_TIMEOUT" }), true);

View File

@@ -8,32 +8,11 @@
*/
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-combo-diagnostics-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const core = await import("../../src/lib/db/core.ts");
const { errorResponseWithComboDiagnostics, sanitizeComboDiagnostics } =
await import("../../open-sse/utils/error.ts");
const { buildRecoveryHint } = await import("../../open-sse/services/combo/pinRecovery.ts");
test.after(() => {
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("combo diagnostics: headers + body carry the sanitized trace (code override preserved)", async () => {
const res = errorResponseWithComboDiagnostics(
503,

View File

@@ -1,608 +1,11 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
const TEST_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-public-errors-"));
const TEST_DATA_DIR = path.join(TEST_ROOT, "data");
const TEST_PLUGINS_DIR = path.join(TEST_ROOT, "plugins");
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
const ORIGINAL_PLUGINS_DIR = process.env.OMNIROUTE_PLUGINS_DIR;
const REPO_ROOT = fileURLToPath(new URL("../..", import.meta.url));
import { runIsolatedBoundaryFixture } from "./helpers/runIsolatedBoundaryFixture.ts";
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
fs.mkdirSync(TEST_PLUGINS_DIR, { recursive: true });
process.env.DATA_DIR = TEST_DATA_DIR;
process.env.OMNIROUTE_PLUGINS_DIR = TEST_PLUGINS_DIR;
const core = await import("../../src/lib/db/core.ts");
const {
buildErrorBody,
buildModelCooldownBody,
createErrorResult,
parseUpstreamError,
projectPublicErrorIdentifier,
providerCircuitOpenResponse,
sanitizeErrorMessage,
sanitizeUpstreamDetails,
unavailableResponse,
} = await import("../../open-sse/utils/error.ts");
const { buildPassthroughErrorResponse, shouldPassthroughUpstreamError } =
await import("../../open-sse/utils/upstreamErrorPassthrough.ts");
test.after(() => {
core.resetDbInstance();
if (ORIGINAL_DATA_DIR === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = ORIGINAL_DATA_DIR;
if (ORIGINAL_PLUGINS_DIR === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = ORIGINAL_PLUGINS_DIR;
fs.rmSync(TEST_ROOT, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("sanitizeErrorMessage removes non-source paths, credentials, and serialized stacks", () => {
const raw = String.raw`Provider failed at /srv/private/provider-key.json access_token=provider-secret\n at validate (C:\Users\admin\private\validator.ts:42:7)`;
const safe = sanitizeErrorMessage(raw);
assert.match(safe, /Provider failed/i);
assert.doesNotMatch(safe, /srv\/private|provider-secret|C:\\Users|validator\.ts/i);
assert.doesNotMatch(safe, /\\n\s*at validate/i);
});
test("sanitizeErrorMessage redacts Windows drive-root-relative filesystem paths", () => {
const plain = sanitizeErrorMessage(
String.raw`Provider failed at \Users\admin\private\secret.txt`
);
const quoted = sanitizeErrorMessage(
String.raw`Provider failed opening "\Windows\Temp\native.dll"`
);
const singleSegment = sanitizeErrorMessage(String.raw`Provider failed opening \private.db`);
const prose = sanitizeErrorMessage(String.raw`Provider reported \offline without a path`);
const escapedInitialPaths = [
String.raw`Provider failed at \bin\private.db`,
String.raw`Provider failed at \folder\private.db`,
String.raw`Provider failed at \new\private.db`,
String.raw`Provider failed at \root\private.db`,
String.raw`Provider failed at \temp\private.db`,
String.raw`Provider failed at C:\temp\private.db`,
].map((message) => sanitizeErrorMessage(message));
assert.equal(plain, "Provider failed at <path>");
assert.equal(quoted, 'Provider failed opening "<path>"');
assert.equal(singleSegment, "Provider failed opening <path>");
assert.equal(prose, String.raw`Provider reported \offline without a path`);
for (const projected of escapedInitialPaths) {
assert.equal(projected, "Provider failed at <path>");
}
});
test("sanitizeErrorMessage redacts extensionless POSIX paths without hiding explicit routes", () => {
const compact = sanitizeErrorMessage("Provider failed at /custom/internal/secret");
const spaced = sanitizeErrorMessage("Provider failed at /custom/internal secret directory");
const route = sanitizeErrorMessage("Route /dashboard/providers is unavailable");
const singleSegment = sanitizeErrorMessage("Provider failed opening /vault");
const singleSegmentRoute = sanitizeErrorMessage("Route /vault is unavailable");
const compoundPathAndRoute = sanitizeErrorMessage(
"Failed /vault then GET /home/profile returned 404"
);
const knownRootRoutes = [
sanitizeErrorMessage("GET /home returned 404"),
sanitizeErrorMessage("Route /run is unavailable"),
sanitizeErrorMessage("POST /data returned 409"),
sanitizeErrorMessage("Route /var is unavailable"),
];
const body = buildErrorBody(500, "Provider failed at /custom/internal/secret");
assert.doesNotMatch(compact, /custom\/internal\/secret/);
assert.doesNotMatch(spaced, /custom\/internal|secret directory/);
assert.doesNotMatch(body.error.message, /custom\/internal\/secret/);
assert.match(compact, /<path>/);
assert.equal(route, "Route /dashboard/providers is unavailable");
assert.equal(singleSegment, "Provider failed opening <path>");
assert.equal(singleSegmentRoute, "Route /vault is unavailable");
assert.equal(compoundPathAndRoute, "Failed <path> then GET /home/profile returned 404");
assert.deepEqual(knownRootRoutes, [
"GET /home returned 404",
"Route /run is unavailable",
"POST /data returned 409",
"Route /var is unavailable",
]);
});
test("sanitizeErrorMessage fails closed when string coercion is hostile", () => {
const hostile = {
toString(): never {
throw new Error("access_token=hostile-secret at /srv/private/hostile.ts:1:2");
},
};
assert.equal(sanitizeErrorMessage(hostile), "");
});
test("buildErrorBody projects untrusted error classifications onto safe identifiers", () => {
const body = buildErrorBody(502, "upstream failed", undefined, {
type: "server_error\nX-Leak: yes",
code: "sk-live-secret-value",
reason: "access_token=reason-secret",
test("public error boundaries pass in an isolated child process", () => {
runIsolatedBoundaryFixture({
fixtureUrl: new URL("./fixtures/error-public-boundaries-hardening.fixture.ts", import.meta.url),
expectedTests: 23,
label: "public error boundaries",
});
assert.equal(body.error.type, "server_error");
assert.equal(body.error.code, "bad_gateway");
assert.equal(body.error.reason, undefined);
});
test("createErrorResult rejects opaque upstream identifiers that could be echoed credentials", async () => {
const opaqueCredential = "AbC9xY7pQ2mN8vR4kL6z";
const result = createErrorResult(
502,
"upstream failed",
null,
opaqueCredential,
opaqueCredential
);
const body = (await result.response.json()) as {
error: { code: string; type: string };
};
assert.equal(body.error.code, "bad_gateway");
assert.equal(body.error.type, "server_error");
assert.doesNotMatch(JSON.stringify(body), new RegExp(opaqueCredential));
});
test("parseUpstreamError never stringifies an untrusted error object into the public message", async () => {
const opaqueIdentifier = "AbC9xY7pQ2mN8vR4kL6z";
const parsed = await parseUpstreamError(
Response.json(
{
error: {
code: opaqueIdentifier,
type: opaqueIdentifier,
reason: opaqueIdentifier,
},
},
{ status: 502 }
),
"openai"
);
const result = createErrorResult(
parsed.statusCode,
parsed.message,
parsed.retryAfterMs,
parsed.errorCode as string,
parsed.errorType as string,
parsed.responseBody
);
const bodyText = await result.response.text();
assert.equal(parsed.message, "Upstream error: 502");
assert.doesNotMatch(bodyText, new RegExp(opaqueIdentifier));
});
test("buildErrorBody preserves the configured empty code for unmapped client statuses", () => {
const body = buildErrorBody(424, "Dependency failed");
assert.equal(body.error.type, "invalid_request_error");
assert.equal(body.error.code, "");
});
test("public identifier vocabulary preserves current internal machine-readable contracts", () => {
const identifiers = [
"context_length_exceeded",
"tool_calling_not_supported",
"vision",
"tools",
"structured_output",
"context_window",
"unsupported_endpoint",
"unverified_codex_client",
"invalid_previous_response_binding",
"incompatible_reasoning_effort",
"STREAM_READINESS_TIMEOUT",
"stream_timeout",
"STREAM_EARLY_EOF",
"stream_early_eof",
"LEASE_NO_ELIGIBLE_CONNECTION",
"LEASE_ELIGIBILITY_UNAVAILABLE",
"LEASE_UNSUPPORTED_ROUTE",
"LEASE_UNSUPPORTED_TRANSPORT",
"DIRECT_RESPONSE_START_TIMEOUT",
"PROXY_FAMILY_UNAVAILABLE",
"RELAY_TIMEOUT",
"TLS_FINGERPRINT_FAILED",
"PROXY_REQUEST_FAILED",
"TLS_SESSION_CAPACITY",
"TLS_CIRCUIT_OPEN",
"PROVIDER_RETIRED",
"upstream_empty_response",
"upstream_response_error",
"upstream_response_failed",
"stream_pipeline_error",
"stream_terminated",
"rate_limited",
"usage_limit_reached",
"timeout",
"semaphore_timeout",
"semaphore_queue_full",
"RATE_LIMIT_EXECUTION_TIMEOUT",
"RATE_LIMIT_QUEUE_FULL",
"RATE_LIMIT_QUEUE_WEDGED",
"RATE_LIMIT_QUEUE_TIMEOUT",
"rate_limit_queue_wedged",
"429",
"empty_response",
"stream_idle_timeout",
"empty_content",
"UNAVAILABLE",
"RESOURCE_EXHAUSTED",
"provider_unavailable",
"unsupported_feature",
"missing_project_id",
"oauth_missing_project_id",
"gcp_project_required",
"QUOTA_ONLY",
"QUOTA_NOT_ALLOCATED",
"cloudflare_challenge",
"cf_mitigated_challenge",
"upstream_protocol_error",
"claude_web_protocol_error",
"service_not_running",
"storage_encryption_stale",
"HTTP_429",
"BLACKBOX_SUBSCRIPTION_REQUIRED",
"BLACKBOX_AUTH_REQUIRED",
"BLACKBOX_RATE_LIMIT",
"abort",
"ABORTED",
"CHIPOTLE_ERROR",
"premium_model_requires_key",
"GROK_ERROR",
"TLS_CLIENT_UNAVAILABLE",
"upstream_access_denied",
"proxy_unavailable",
"EXECUTOR_ERROR",
"executor_contract_violation",
"orphan_tool_result",
"bedrock_stream_error",
"invalid_kiro_tool_call",
"devin_cli_error",
"upstream_websocket_error",
"upstream_websocket_connect_failed",
"codex_app_server_turn_failed",
"missing_credits",
"reached_limit",
"rate_limit_reached",
"rate_limit_longer_reached",
"client_cancelled",
"client_closed_request",
"compaction_control_unavailable",
"compaction_handoff_failed",
"connector_not_found",
"connector_error",
"prompt_attachment_integrity",
"chatgpt_session_expired",
"chatgpt_subscription_unavailable",
"upstream_server_error",
"multipart_protocol_violation",
"browser_stream_inconsistent",
"structured_output_validation_failed",
"chatgpt_submission_ambiguous",
"chatgpt_submitted_turn_failed",
"cli_not_found",
"upstream_auth_error",
"wreq_unavailable",
"api_error",
"connection_error",
"unsupported_runtime",
"VIDEO_ARTIFACT_URL_INVALID",
"VIDEO_ARTIFACT_URL_BLOCKED",
"VIDEO_ARTIFACT_DOWNLOAD_FAILED",
"VIDEO_ARTIFACT_TOO_LARGE",
"VIDEO_ARTIFACT_SIGNATURE_INVALID",
"VIDEO_ARTIFACT_NOT_READY",
"VIDEO_ARTIFACT_UNAVAILABLE",
"VIDEO_ARTIFACT_CONTENT_TYPE_INVALID",
"codex_app_server_unconfigured",
"meta_ai_warmup_failed",
"meta_ai_mode_switch_failed",
"meta_ai_ws_error",
"meta_ai_empty_response",
"PPLX_ERROR",
"cloudflare_or_bot",
"request_failed",
"lmarena_error",
"network_error",
];
for (const identifier of identifiers) {
assert.equal(projectPublicErrorIdentifier(identifier, "bad_request"), identifier, identifier);
}
});
test("public numeric identifiers are limited to three-digit HTTP status codes", () => {
assert.equal(projectPublicErrorIdentifier("100", "bad_request"), "100");
assert.equal(projectPublicErrorIdentifier("599", "bad_request"), "599");
assert.equal(projectPublicErrorIdentifier("099", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("600", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("5000", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("40002", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("HTTP_600", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("HTTP_40002", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("weird_error", "bad_gateway"), "bad_gateway");
});
test("buildErrorBody callers never overwrite a projected public classification", () => {
const productionFiles: string[] = [];
const collectTypeScriptFiles = (directory: string): void => {
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
const entryPath = path.join(directory, entry.name);
if (entry.isDirectory()) {
if (entry.name === "__tests__") continue;
collectTypeScriptFiles(entryPath);
} else if (entry.isFile() && /\.tsx?$/.test(entry.name)) {
productionFiles.push(entryPath);
}
}
};
collectTypeScriptFiles(path.join(REPO_ROOT, "open-sse"));
collectTypeScriptFiles(path.join(REPO_ROOT, "src"));
const mutationPattern = /\b[A-Za-z_$][A-Za-z0-9_$]*\.error\.(?:code|type|reason)\s*=(?!=)/g;
const violations: string[] = [];
for (const filePath of productionFiles) {
const source = fs.readFileSync(filePath, "utf8");
if (!source.includes("buildErrorBody")) continue;
for (const match of source.matchAll(mutationPattern)) {
const line = source.slice(0, match.index).split("\n").length;
violations.push(`${path.relative(REPO_ROOT, filePath)}:${line}`);
}
}
assert.deepEqual(violations, []);
const chatCoreSource = fs.readFileSync(
path.join(REPO_ROOT, "open-sse/handlers/chatCore.ts"),
"utf8"
);
assert.doesNotMatch(
chatCoreSource,
/JSON\.stringify\(\s*\{\s*error\s*:\s*\{/,
"chatCore must not bypass buildErrorBody with a manually assembled error envelope"
);
});
test("operational log persistence catches use the canonical sanitizer", () => {
const callLogsSource = fs.readFileSync(path.join(REPO_ROOT, "src/lib/usage/callLogs.ts"), "utf8");
const proxyLoggerSource = fs.readFileSync(path.join(REPO_ROOT, "src/lib/proxyLogger.ts"), "utf8");
assert.match(callLogsSource, /sanitizeErrorMessage\(error\)/);
assert.doesNotMatch(callLogsSource, /\(error as Error\)\.message/);
assert.match(proxyLoggerSource, /sanitizeErrorMessage\(err\)/);
assert.doesNotMatch(proxyLoggerSource, /err\?\.message\s*\|\|\s*err/);
});
test("stream request finalization never warns with a raw error object", () => {
const source = fs.readFileSync(
path.join(REPO_ROOT, "open-sse/utils/streamFailureFinalization.ts"),
"utf8"
);
assert.match(source, /sanitizeErrorMessage\(error\)/);
assert.doesNotMatch(source, /"message" in error[\s\S]{0,160}: error/);
});
test("chatCore provider-failure writes use the projected persistent message", () => {
const source = fs.readFileSync(path.join(REPO_ROOT, "open-sse/handlers/chatCore.ts"), "utf8");
const failureStart = source.indexOf("providerFailure: if (!providerResponse.ok)");
const failureEnd = source.indexOf("// Non-streaming response", failureStart);
assert.ok(failureStart >= 0 && failureEnd > failureStart, "providerFailure block must exist");
const failureBlock = source.slice(failureStart, failureEnd);
assert.doesNotMatch(failureBlock, /lastError:\s*message\b/);
assert.ok(
(failureBlock.match(/lastError:\s*persistentMessage\b/g) || []).length >= 11,
"every providerFailure persistence branch must use persistentMessage"
);
});
test("public cooldown and circuit responses sanitize dynamic context", async () => {
const unavailable = unavailableResponse(
503,
"Provider failed at /srv/private/state.sqlite access_token=unavailable-secret",
5,
"retry after reading C:\\Users\\admin\\private\\state.json"
);
const unavailableBody = (await unavailable.json()) as { error: { message: string } };
assert.doesNotMatch(unavailableBody.error.message, /srv\/private|unavailable-secret|C:\\Users/i);
const circuit = providerCircuitOpenResponse(
"provider access_token=circuit-secret /home/service/provider.json",
5
);
const circuitBody = (await circuit.json()) as {
error: { message: string; provider: string };
};
assert.equal(circuitBody.error.provider, "unknown");
assert.doesNotMatch(JSON.stringify(circuitBody), /circuit-secret|\/home\/service/i);
const cooldown = buildModelCooldownBody({
model: "model access_token=model-secret /opt/models/private.json",
retryAfterSec: Number.NaN,
retryAfterAt: "not-a-timestamp access_token=timestamp-secret",
});
assert.equal(cooldown.error.model, undefined);
assert.equal(cooldown.error.retry_after, undefined);
assert.equal(cooldown.error.reset_seconds, 1);
assert.doesNotMatch(JSON.stringify(cooldown), /model-secret|timestamp-secret|\/opt\/models/i);
});
test("sanitizeUpstreamDetails drops credential aliases and prototype-control keys", () => {
const input = Object.create(null) as Record<string, unknown>;
input.error = {
message: "quota metadata at /srv/provider/private.json",
credential: "credential-secret",
sessionId: "session-secret",
session_count: 2,
};
input.__proto__ = { leaked: true };
const safe = sanitizeUpstreamDetails(input) as Record<string, unknown>;
const serialized = JSON.stringify(safe);
assert.doesNotMatch(serialized, /credential-secret|session-secret|srv\/provider|__proto__/i);
assert.match(serialized, /"session_count":2/);
});
test("buildErrorBody fails closed for hostile upstream detail accessors", () => {
const hostile = new Proxy(
{},
{
ownKeys(): never {
throw new Error("access_token=hostile-detail at /srv/private/detail.ts:1:2");
},
}
);
let body: ReturnType<typeof buildErrorBody> | undefined;
assert.doesNotThrow(() => {
body = buildErrorBody(502, "upstream failed", hostile);
});
assert.equal(body?.upstream_details, undefined);
assert.doesNotMatch(JSON.stringify(body), /hostile-detail|srv\/private|detail\.ts/i);
});
test("upstream passthrough preserves safe wording but recursively sanitizes the JSON body", async () => {
const opaqueIdentifier = "AbC9xY7pQ2mN8vR4kL6z";
const upstream = {
type: "error",
error: {
type: "invalid_request_error",
code: opaqueIdentifier,
reason: opaqueIdentifier,
message: "quota metadata from /srv/provider/private.json",
credential: "credential-secret",
session_count: 2,
details: [{ type: "integer", reason: "must be positive" }],
},
};
assert.equal(shouldPassthroughUpstreamError(422, upstream), true);
const response = buildPassthroughErrorResponse(422, upstream);
assert.ok(response);
const serialized = JSON.stringify(await response.json());
assert.match(serialized, /invalid_request_error/);
assert.match(serialized, /"session_count":2/);
assert.match(serialized, /"type":"integer","reason":"must be positive"/);
assert.doesNotMatch(
serialized,
new RegExp(`credential-secret|srv/provider|${opaqueIdentifier}`, "i")
);
});
test("upstream classification projection preserves HTTP numbers and rejects opaque aliases", () => {
const opaqueIdentifier = "AbC9xY7pQ2mN8vR4kL6z";
const projected = sanitizeUpstreamDetails({
code: 400,
status: "UNAVAILABLE",
oversizedCode: 40002,
error: {
code: 40002,
error_code: opaqueIdentifier,
errorCode: opaqueIdentifier,
error_type: opaqueIdentifier,
errorType: opaqueIdentifier,
sub_type: opaqueIdentifier,
subType: opaqueIdentifier,
status: opaqueIdentifier,
status_code: opaqueIdentifier,
statusCode: opaqueIdentifier,
message: "safe provider wording",
},
}) as {
code?: unknown;
status?: unknown;
oversizedCode?: unknown;
error?: Record<string, unknown>;
};
assert.equal(projected.code, 400);
assert.equal(projected.status, "UNAVAILABLE");
assert.equal(projected.oversizedCode, 40002);
assert.equal(projected.error?.code, undefined);
assert.equal(projected.error?.error_code, "");
assert.equal(projected.error?.errorCode, "");
assert.equal(projected.error?.error_type, "upstream_error");
assert.equal(projected.error?.errorType, "upstream_error");
assert.equal(projected.error?.sub_type, "upstream_error");
assert.equal(projected.error?.subType, "upstream_error");
assert.equal(projected.error?.status, undefined);
assert.equal(projected.error?.status_code, undefined);
assert.equal(projected.error?.statusCode, undefined);
assert.equal(projected.error?.message, "safe provider wording");
assert.doesNotMatch(JSON.stringify(projected), new RegExp(opaqueIdentifier));
});
test("upstream classification projection preserves only real gRPC numeric codes", () => {
const projected = sanitizeUpstreamDetails({
error: { code: 7 },
errors: [{ code: 16 }, { code: 17 }, { code: 40002 }],
status: 7,
warning: { code: "model_capacity", type: "unknown" },
}) as {
error?: { code?: unknown };
errors?: Array<{ code?: unknown }>;
status?: unknown;
warning?: { code?: unknown; type?: unknown };
};
assert.equal(projected.error?.code, 7);
assert.equal(projected.errors?.[0]?.code, 16);
assert.equal(projected.errors?.[1]?.code, undefined);
assert.equal(projected.errors?.[2]?.code, undefined);
assert.equal(projected.status, undefined);
assert.equal(projected.warning?.code, "");
assert.equal(projected.warning?.type, "upstream_error");
});
test("sanitizeUpstreamDetails fails closed for hostile prototype access", () => {
const hostile = new Proxy(
{},
{
getPrototypeOf(): never {
throw new Error("access_token=prototype-secret at /srv/private/prototype.ts");
},
}
);
let projected: unknown;
assert.doesNotThrow(() => {
projected = sanitizeUpstreamDetails(hostile);
});
assert.doesNotMatch(JSON.stringify(projected), /prototype-secret|srv\/private|prototype\.ts/i);
});
test("upstream passthrough fails closed for non-serializable bodies", () => {
const cyclic: Record<string, unknown> = { error: { message: "safe" } };
cyclic.self = cyclic;
assert.equal(shouldPassthroughUpstreamError(400, cyclic), false);
assert.equal(buildPassthroughErrorResponse(400, cyclic), null);
});
test("upstream passthrough fails closed when getters change after eligibility", () => {
let reads = 0;
const upstream = Object.create(null) as Record<string, unknown>;
Object.defineProperty(upstream, "error", {
enumerable: true,
get(): unknown {
reads += 1;
if (reads === 1) return { message: "safe capability error" };
throw new Error("access_token=second-read-secret at /srv/private/getter.ts:1:2");
},
});
assert.doesNotThrow(() => buildPassthroughErrorResponse(400, upstream));
assert.equal(buildPassthroughErrorResponse(400, upstream), null);
});

View File

@@ -1,29 +1,9 @@
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-error-sensitive-redaction-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const core = await import("../../src/lib/db/core.ts");
const { sanitizeErrorMessage, sanitizeUpstreamDetails } =
await import("../../open-sse/utils/errorSanitization.ts");
test.after(() => {
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
import {
sanitizeErrorMessage,
sanitizeUpstreamDetails,
} from "../../open-sse/utils/errorSanitization.ts";
test("sanitizeErrorMessage removes bearer credentials and image data URLs", () => {
const raw =

View File

@@ -0,0 +1,608 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
const TEST_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-public-errors-"));
const TEST_DATA_DIR = path.join(TEST_ROOT, "data");
const TEST_PLUGINS_DIR = path.join(TEST_ROOT, "plugins");
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
const ORIGINAL_PLUGINS_DIR = process.env.OMNIROUTE_PLUGINS_DIR;
const REPO_ROOT = fileURLToPath(new URL("../../..", import.meta.url));
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
fs.mkdirSync(TEST_PLUGINS_DIR, { recursive: true });
process.env.DATA_DIR = TEST_DATA_DIR;
process.env.OMNIROUTE_PLUGINS_DIR = TEST_PLUGINS_DIR;
const core = await import("../../../src/lib/db/core.ts");
const {
buildErrorBody,
buildModelCooldownBody,
createErrorResult,
parseUpstreamError,
projectPublicErrorIdentifier,
providerCircuitOpenResponse,
sanitizeErrorMessage,
sanitizeUpstreamDetails,
unavailableResponse,
} = await import("../../../open-sse/utils/error.ts");
const { buildPassthroughErrorResponse, shouldPassthroughUpstreamError } =
await import("../../../open-sse/utils/upstreamErrorPassthrough.ts");
test.after(() => {
core.resetDbInstance();
if (ORIGINAL_DATA_DIR === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = ORIGINAL_DATA_DIR;
if (ORIGINAL_PLUGINS_DIR === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = ORIGINAL_PLUGINS_DIR;
fs.rmSync(TEST_ROOT, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("sanitizeErrorMessage removes non-source paths, credentials, and serialized stacks", () => {
const raw = String.raw`Provider failed at /srv/private/provider-key.json access_token=provider-secret\n at validate (C:\Users\admin\private\validator.ts:42:7)`;
const safe = sanitizeErrorMessage(raw);
assert.match(safe, /Provider failed/i);
assert.doesNotMatch(safe, /srv\/private|provider-secret|C:\\Users|validator\.ts/i);
assert.doesNotMatch(safe, /\\n\s*at validate/i);
});
test("sanitizeErrorMessage redacts Windows drive-root-relative filesystem paths", () => {
const plain = sanitizeErrorMessage(
String.raw`Provider failed at \Users\admin\private\secret.txt`
);
const quoted = sanitizeErrorMessage(
String.raw`Provider failed opening "\Windows\Temp\native.dll"`
);
const singleSegment = sanitizeErrorMessage(String.raw`Provider failed opening \private.db`);
const prose = sanitizeErrorMessage(String.raw`Provider reported \offline without a path`);
const escapedInitialPaths = [
String.raw`Provider failed at \bin\private.db`,
String.raw`Provider failed at \folder\private.db`,
String.raw`Provider failed at \new\private.db`,
String.raw`Provider failed at \root\private.db`,
String.raw`Provider failed at \temp\private.db`,
String.raw`Provider failed at C:\temp\private.db`,
].map((message) => sanitizeErrorMessage(message));
assert.equal(plain, "Provider failed at <path>");
assert.equal(quoted, 'Provider failed opening "<path>"');
assert.equal(singleSegment, "Provider failed opening <path>");
assert.equal(prose, String.raw`Provider reported \offline without a path`);
for (const projected of escapedInitialPaths) {
assert.equal(projected, "Provider failed at <path>");
}
});
test("sanitizeErrorMessage redacts extensionless POSIX paths without hiding explicit routes", () => {
const compact = sanitizeErrorMessage("Provider failed at /custom/internal/secret");
const spaced = sanitizeErrorMessage("Provider failed at /custom/internal secret directory");
const route = sanitizeErrorMessage("Route /dashboard/providers is unavailable");
const singleSegment = sanitizeErrorMessage("Provider failed opening /vault");
const singleSegmentRoute = sanitizeErrorMessage("Route /vault is unavailable");
const compoundPathAndRoute = sanitizeErrorMessage(
"Failed /vault then GET /home/profile returned 404"
);
const knownRootRoutes = [
sanitizeErrorMessage("GET /home returned 404"),
sanitizeErrorMessage("Route /run is unavailable"),
sanitizeErrorMessage("POST /data returned 409"),
sanitizeErrorMessage("Route /var is unavailable"),
];
const body = buildErrorBody(500, "Provider failed at /custom/internal/secret");
assert.doesNotMatch(compact, /custom\/internal\/secret/);
assert.doesNotMatch(spaced, /custom\/internal|secret directory/);
assert.doesNotMatch(body.error.message, /custom\/internal\/secret/);
assert.match(compact, /<path>/);
assert.equal(route, "Route /dashboard/providers is unavailable");
assert.equal(singleSegment, "Provider failed opening <path>");
assert.equal(singleSegmentRoute, "Route /vault is unavailable");
assert.equal(compoundPathAndRoute, "Failed <path> then GET /home/profile returned 404");
assert.deepEqual(knownRootRoutes, [
"GET /home returned 404",
"Route /run is unavailable",
"POST /data returned 409",
"Route /var is unavailable",
]);
});
test("sanitizeErrorMessage fails closed when string coercion is hostile", () => {
const hostile = {
toString(): never {
throw new Error("access_token=hostile-secret at /srv/private/hostile.ts:1:2");
},
};
assert.equal(sanitizeErrorMessage(hostile), "");
});
test("buildErrorBody projects untrusted error classifications onto safe identifiers", () => {
const body = buildErrorBody(502, "upstream failed", undefined, {
type: "server_error\nX-Leak: yes",
code: "sk-live-secret-value",
reason: "access_token=reason-secret",
});
assert.equal(body.error.type, "server_error");
assert.equal(body.error.code, "bad_gateway");
assert.equal(body.error.reason, undefined);
});
test("createErrorResult rejects opaque upstream identifiers that could be echoed credentials", async () => {
const opaqueCredential = "AbC9xY7pQ2mN8vR4kL6z";
const result = createErrorResult(
502,
"upstream failed",
null,
opaqueCredential,
opaqueCredential
);
const body = (await result.response.json()) as {
error: { code: string; type: string };
};
assert.equal(body.error.code, "bad_gateway");
assert.equal(body.error.type, "server_error");
assert.doesNotMatch(JSON.stringify(body), new RegExp(opaqueCredential));
});
test("parseUpstreamError never stringifies an untrusted error object into the public message", async () => {
const opaqueIdentifier = "AbC9xY7pQ2mN8vR4kL6z";
const parsed = await parseUpstreamError(
Response.json(
{
error: {
code: opaqueIdentifier,
type: opaqueIdentifier,
reason: opaqueIdentifier,
},
},
{ status: 502 }
),
"openai"
);
const result = createErrorResult(
parsed.statusCode,
parsed.message,
parsed.retryAfterMs,
parsed.errorCode as string,
parsed.errorType as string,
parsed.responseBody
);
const bodyText = await result.response.text();
assert.equal(parsed.message, "Upstream error: 502");
assert.doesNotMatch(bodyText, new RegExp(opaqueIdentifier));
});
test("buildErrorBody preserves the configured empty code for unmapped client statuses", () => {
const body = buildErrorBody(424, "Dependency failed");
assert.equal(body.error.type, "invalid_request_error");
assert.equal(body.error.code, "");
});
test("public identifier vocabulary preserves current internal machine-readable contracts", () => {
const identifiers = [
"context_length_exceeded",
"tool_calling_not_supported",
"vision",
"tools",
"structured_output",
"context_window",
"unsupported_endpoint",
"unverified_codex_client",
"invalid_previous_response_binding",
"incompatible_reasoning_effort",
"STREAM_READINESS_TIMEOUT",
"stream_timeout",
"STREAM_EARLY_EOF",
"stream_early_eof",
"LEASE_NO_ELIGIBLE_CONNECTION",
"LEASE_ELIGIBILITY_UNAVAILABLE",
"LEASE_UNSUPPORTED_ROUTE",
"LEASE_UNSUPPORTED_TRANSPORT",
"DIRECT_RESPONSE_START_TIMEOUT",
"PROXY_FAMILY_UNAVAILABLE",
"RELAY_TIMEOUT",
"TLS_FINGERPRINT_FAILED",
"PROXY_REQUEST_FAILED",
"TLS_SESSION_CAPACITY",
"TLS_CIRCUIT_OPEN",
"PROVIDER_RETIRED",
"upstream_empty_response",
"upstream_response_error",
"upstream_response_failed",
"stream_pipeline_error",
"stream_terminated",
"rate_limited",
"usage_limit_reached",
"timeout",
"semaphore_timeout",
"semaphore_queue_full",
"RATE_LIMIT_EXECUTION_TIMEOUT",
"RATE_LIMIT_QUEUE_FULL",
"RATE_LIMIT_QUEUE_WEDGED",
"RATE_LIMIT_QUEUE_TIMEOUT",
"rate_limit_queue_wedged",
"429",
"empty_response",
"stream_idle_timeout",
"empty_content",
"UNAVAILABLE",
"RESOURCE_EXHAUSTED",
"provider_unavailable",
"unsupported_feature",
"missing_project_id",
"oauth_missing_project_id",
"gcp_project_required",
"QUOTA_ONLY",
"QUOTA_NOT_ALLOCATED",
"cloudflare_challenge",
"cf_mitigated_challenge",
"upstream_protocol_error",
"claude_web_protocol_error",
"service_not_running",
"storage_encryption_stale",
"HTTP_429",
"BLACKBOX_SUBSCRIPTION_REQUIRED",
"BLACKBOX_AUTH_REQUIRED",
"BLACKBOX_RATE_LIMIT",
"abort",
"ABORTED",
"CHIPOTLE_ERROR",
"premium_model_requires_key",
"GROK_ERROR",
"TLS_CLIENT_UNAVAILABLE",
"upstream_access_denied",
"proxy_unavailable",
"EXECUTOR_ERROR",
"executor_contract_violation",
"orphan_tool_result",
"bedrock_stream_error",
"invalid_kiro_tool_call",
"devin_cli_error",
"upstream_websocket_error",
"upstream_websocket_connect_failed",
"codex_app_server_turn_failed",
"missing_credits",
"reached_limit",
"rate_limit_reached",
"rate_limit_longer_reached",
"client_cancelled",
"client_closed_request",
"compaction_control_unavailable",
"compaction_handoff_failed",
"connector_not_found",
"connector_error",
"prompt_attachment_integrity",
"chatgpt_session_expired",
"chatgpt_subscription_unavailable",
"upstream_server_error",
"multipart_protocol_violation",
"browser_stream_inconsistent",
"structured_output_validation_failed",
"chatgpt_submission_ambiguous",
"chatgpt_submitted_turn_failed",
"cli_not_found",
"upstream_auth_error",
"wreq_unavailable",
"api_error",
"connection_error",
"unsupported_runtime",
"VIDEO_ARTIFACT_URL_INVALID",
"VIDEO_ARTIFACT_URL_BLOCKED",
"VIDEO_ARTIFACT_DOWNLOAD_FAILED",
"VIDEO_ARTIFACT_TOO_LARGE",
"VIDEO_ARTIFACT_SIGNATURE_INVALID",
"VIDEO_ARTIFACT_NOT_READY",
"VIDEO_ARTIFACT_UNAVAILABLE",
"VIDEO_ARTIFACT_CONTENT_TYPE_INVALID",
"codex_app_server_unconfigured",
"meta_ai_warmup_failed",
"meta_ai_mode_switch_failed",
"meta_ai_ws_error",
"meta_ai_empty_response",
"PPLX_ERROR",
"cloudflare_or_bot",
"request_failed",
"lmarena_error",
"network_error",
];
for (const identifier of identifiers) {
assert.equal(projectPublicErrorIdentifier(identifier, "bad_request"), identifier, identifier);
}
});
test("public numeric identifiers are limited to three-digit HTTP status codes", () => {
assert.equal(projectPublicErrorIdentifier("100", "bad_request"), "100");
assert.equal(projectPublicErrorIdentifier("599", "bad_request"), "599");
assert.equal(projectPublicErrorIdentifier("099", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("600", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("5000", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("40002", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("HTTP_600", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("HTTP_40002", "bad_request"), "bad_request");
assert.equal(projectPublicErrorIdentifier("weird_error", "bad_gateway"), "bad_gateway");
});
test("buildErrorBody callers never overwrite a projected public classification", () => {
const productionFiles: string[] = [];
const collectTypeScriptFiles = (directory: string): void => {
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
const entryPath = path.join(directory, entry.name);
if (entry.isDirectory()) {
if (entry.name === "__tests__") continue;
collectTypeScriptFiles(entryPath);
} else if (entry.isFile() && /\.tsx?$/.test(entry.name)) {
productionFiles.push(entryPath);
}
}
};
collectTypeScriptFiles(path.join(REPO_ROOT, "open-sse"));
collectTypeScriptFiles(path.join(REPO_ROOT, "src"));
const mutationPattern = /\b[A-Za-z_$][A-Za-z0-9_$]*\.error\.(?:code|type|reason)\s*=(?!=)/g;
const violations: string[] = [];
for (const filePath of productionFiles) {
const source = fs.readFileSync(filePath, "utf8");
if (!source.includes("buildErrorBody")) continue;
for (const match of source.matchAll(mutationPattern)) {
const line = source.slice(0, match.index).split("\n").length;
violations.push(`${path.relative(REPO_ROOT, filePath)}:${line}`);
}
}
assert.deepEqual(violations, []);
const chatCoreSource = fs.readFileSync(
path.join(REPO_ROOT, "open-sse/handlers/chatCore.ts"),
"utf8"
);
assert.doesNotMatch(
chatCoreSource,
/JSON\.stringify\(\s*\{\s*error\s*:\s*\{/,
"chatCore must not bypass buildErrorBody with a manually assembled error envelope"
);
});
test("operational log persistence catches use the canonical sanitizer", () => {
const callLogsSource = fs.readFileSync(path.join(REPO_ROOT, "src/lib/usage/callLogs.ts"), "utf8");
const proxyLoggerSource = fs.readFileSync(path.join(REPO_ROOT, "src/lib/proxyLogger.ts"), "utf8");
assert.match(callLogsSource, /sanitizeErrorMessage\(error\)/);
assert.doesNotMatch(callLogsSource, /\(error as Error\)\.message/);
assert.match(proxyLoggerSource, /sanitizeErrorMessage\(err\)/);
assert.doesNotMatch(proxyLoggerSource, /err\?\.message\s*\|\|\s*err/);
});
test("stream request finalization never warns with a raw error object", () => {
const source = fs.readFileSync(
path.join(REPO_ROOT, "open-sse/utils/streamFailureFinalization.ts"),
"utf8"
);
assert.match(source, /sanitizeErrorMessage\(error\)/);
assert.doesNotMatch(source, /"message" in error[\s\S]{0,160}: error/);
});
test("chatCore provider-failure writes use the projected persistent message", () => {
const source = fs.readFileSync(path.join(REPO_ROOT, "open-sse/handlers/chatCore.ts"), "utf8");
const failureStart = source.indexOf("providerFailure: if (!providerResponse.ok)");
const failureEnd = source.indexOf("// Non-streaming response", failureStart);
assert.ok(failureStart >= 0 && failureEnd > failureStart, "providerFailure block must exist");
const failureBlock = source.slice(failureStart, failureEnd);
assert.doesNotMatch(failureBlock, /lastError:\s*message\b/);
assert.ok(
(failureBlock.match(/lastError:\s*persistentMessage\b/g) || []).length >= 11,
"every providerFailure persistence branch must use persistentMessage"
);
});
test("public cooldown and circuit responses sanitize dynamic context", async () => {
const unavailable = unavailableResponse(
503,
"Provider failed at /srv/private/state.sqlite access_token=unavailable-secret",
5,
"retry after reading C:\\Users\\admin\\private\\state.json"
);
const unavailableBody = (await unavailable.json()) as { error: { message: string } };
assert.doesNotMatch(unavailableBody.error.message, /srv\/private|unavailable-secret|C:\\Users/i);
const circuit = providerCircuitOpenResponse(
"provider access_token=circuit-secret /home/service/provider.json",
5
);
const circuitBody = (await circuit.json()) as {
error: { message: string; provider: string };
};
assert.equal(circuitBody.error.provider, "unknown");
assert.doesNotMatch(JSON.stringify(circuitBody), /circuit-secret|\/home\/service/i);
const cooldown = buildModelCooldownBody({
model: "model access_token=model-secret /opt/models/private.json",
retryAfterSec: Number.NaN,
retryAfterAt: "not-a-timestamp access_token=timestamp-secret",
});
assert.equal(cooldown.error.model, undefined);
assert.equal(cooldown.error.retry_after, undefined);
assert.equal(cooldown.error.reset_seconds, 1);
assert.doesNotMatch(JSON.stringify(cooldown), /model-secret|timestamp-secret|\/opt\/models/i);
});
test("sanitizeUpstreamDetails drops credential aliases and prototype-control keys", () => {
const input = Object.create(null) as Record<string, unknown>;
input.error = {
message: "quota metadata at /srv/provider/private.json",
credential: "credential-secret",
sessionId: "session-secret",
session_count: 2,
};
input.__proto__ = { leaked: true };
const safe = sanitizeUpstreamDetails(input) as Record<string, unknown>;
const serialized = JSON.stringify(safe);
assert.doesNotMatch(serialized, /credential-secret|session-secret|srv\/provider|__proto__/i);
assert.match(serialized, /"session_count":2/);
});
test("buildErrorBody fails closed for hostile upstream detail accessors", () => {
const hostile = new Proxy(
{},
{
ownKeys(): never {
throw new Error("access_token=hostile-detail at /srv/private/detail.ts:1:2");
},
}
);
let body: ReturnType<typeof buildErrorBody> | undefined;
assert.doesNotThrow(() => {
body = buildErrorBody(502, "upstream failed", hostile);
});
assert.equal(body?.upstream_details, undefined);
assert.doesNotMatch(JSON.stringify(body), /hostile-detail|srv\/private|detail\.ts/i);
});
test("upstream passthrough preserves safe wording but recursively sanitizes the JSON body", async () => {
const opaqueIdentifier = "AbC9xY7pQ2mN8vR4kL6z";
const upstream = {
type: "error",
error: {
type: "invalid_request_error",
code: opaqueIdentifier,
reason: opaqueIdentifier,
message: "quota metadata from /srv/provider/private.json",
credential: "credential-secret",
session_count: 2,
details: [{ type: "integer", reason: "must be positive" }],
},
};
assert.equal(shouldPassthroughUpstreamError(422, upstream), true);
const response = buildPassthroughErrorResponse(422, upstream);
assert.ok(response);
const serialized = JSON.stringify(await response.json());
assert.match(serialized, /invalid_request_error/);
assert.match(serialized, /"session_count":2/);
assert.match(serialized, /"type":"integer","reason":"must be positive"/);
assert.doesNotMatch(
serialized,
new RegExp(`credential-secret|srv/provider|${opaqueIdentifier}`, "i")
);
});
test("upstream classification projection preserves HTTP numbers and rejects opaque aliases", () => {
const opaqueIdentifier = "AbC9xY7pQ2mN8vR4kL6z";
const projected = sanitizeUpstreamDetails({
code: 400,
status: "UNAVAILABLE",
oversizedCode: 40002,
error: {
code: 40002,
error_code: opaqueIdentifier,
errorCode: opaqueIdentifier,
error_type: opaqueIdentifier,
errorType: opaqueIdentifier,
sub_type: opaqueIdentifier,
subType: opaqueIdentifier,
status: opaqueIdentifier,
status_code: opaqueIdentifier,
statusCode: opaqueIdentifier,
message: "safe provider wording",
},
}) as {
code?: unknown;
status?: unknown;
oversizedCode?: unknown;
error?: Record<string, unknown>;
};
assert.equal(projected.code, 400);
assert.equal(projected.status, "UNAVAILABLE");
assert.equal(projected.oversizedCode, 40002);
assert.equal(projected.error?.code, undefined);
assert.equal(projected.error?.error_code, "");
assert.equal(projected.error?.errorCode, "");
assert.equal(projected.error?.error_type, "upstream_error");
assert.equal(projected.error?.errorType, "upstream_error");
assert.equal(projected.error?.sub_type, "upstream_error");
assert.equal(projected.error?.subType, "upstream_error");
assert.equal(projected.error?.status, undefined);
assert.equal(projected.error?.status_code, undefined);
assert.equal(projected.error?.statusCode, undefined);
assert.equal(projected.error?.message, "safe provider wording");
assert.doesNotMatch(JSON.stringify(projected), new RegExp(opaqueIdentifier));
});
test("upstream classification projection preserves only real gRPC numeric codes", () => {
const projected = sanitizeUpstreamDetails({
error: { code: 7 },
errors: [{ code: 16 }, { code: 17 }, { code: 40002 }],
status: 7,
warning: { code: "model_capacity", type: "unknown" },
}) as {
error?: { code?: unknown };
errors?: Array<{ code?: unknown }>;
status?: unknown;
warning?: { code?: unknown; type?: unknown };
};
assert.equal(projected.error?.code, 7);
assert.equal(projected.errors?.[0]?.code, 16);
assert.equal(projected.errors?.[1]?.code, undefined);
assert.equal(projected.errors?.[2]?.code, undefined);
assert.equal(projected.status, undefined);
assert.equal(projected.warning?.code, "");
assert.equal(projected.warning?.type, "upstream_error");
});
test("sanitizeUpstreamDetails fails closed for hostile prototype access", () => {
const hostile = new Proxy(
{},
{
getPrototypeOf(): never {
throw new Error("access_token=prototype-secret at /srv/private/prototype.ts");
},
}
);
let projected: unknown;
assert.doesNotThrow(() => {
projected = sanitizeUpstreamDetails(hostile);
});
assert.doesNotMatch(JSON.stringify(projected), /prototype-secret|srv\/private|prototype\.ts/i);
});
test("upstream passthrough fails closed for non-serializable bodies", () => {
const cyclic: Record<string, unknown> = { error: { message: "safe" } };
cyclic.self = cyclic;
assert.equal(shouldPassthroughUpstreamError(400, cyclic), false);
assert.equal(buildPassthroughErrorResponse(400, cyclic), null);
});
test("upstream passthrough fails closed when getters change after eligibility", () => {
let reads = 0;
const upstream = Object.create(null) as Record<string, unknown>;
Object.defineProperty(upstream, "error", {
enumerable: true,
get(): unknown {
reads += 1;
if (reads === 1) return { message: "safe capability error" };
throw new Error("access_token=second-read-secret at /srv/private/getter.ts:1:2");
},
});
assert.doesNotThrow(() => buildPassthroughErrorResponse(400, upstream));
assert.equal(buildPassthroughErrorResponse(400, upstream), null);
});

View File

@@ -0,0 +1,184 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-mcp-error-boundaries-"));
const repoRoot = fileURLToPath(new URL("../../..", import.meta.url));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
const originalApiKey = process.env.OMNIROUTE_API_KEY;
const originalApiKeyId = process.env.OMNIROUTE_API_KEY_ID;
const originalInternalToken = process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN;
const originalInternalTokenFile = process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE;
const originalBaseUrl = process.env.OMNIROUTE_BASE_URL;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
process.env.OMNIROUTE_API_KEY = "mcp-boundary-test-key";
process.env.OMNIROUTE_API_KEY_ID = "mcp-boundary-test-key-id";
process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN = "mcp-boundary-internal-test-token";
process.env.OMNIROUTE_BASE_URL = "http://localhost:20128";
delete process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE;
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const { createMcpServer } = await import("../../../open-sse/mcp-server/server.ts");
const { closeAuditDb, queryAuditEntries } = await import("../../../open-sse/mcp-server/audit.ts");
const { obsidianTools } = await import("../../../open-sse/mcp-server/tools/obsidianTools.ts");
const { skillTools } = await import("../../../open-sse/mcp-server/tools/skillTools.ts");
const { skillRegistry } = await import("../../../src/lib/skills/registry.ts");
const { skillExecutor } = await import("../../../src/lib/skills/executor.ts");
const core = await import("../../../src/lib/db/core.ts");
type McpResult = {
content?: Array<{ type: string; text: string }>;
isError?: boolean;
};
type RegisteredTool = {
handler: (args: unknown, extra?: unknown) => Promise<McpResult>;
};
function getRegisteredHandler(server: unknown, toolName: string): RegisteredTool["handler"] {
const registry = (server as { _registeredTools?: Record<string, RegisteredTool> })
._registeredTools;
assert.ok(registry, "McpServer should expose _registeredTools");
const tool = registry[toolName];
assert.ok(tool, `${toolName} must be registered`);
return tool.handler;
}
function assertPublicMcpError(result: McpResult): void {
const text = result.content?.[0]?.text ?? "";
assert.equal(result.isError, true);
assert.match(text, /Error:/);
assert.doesNotMatch(text, /mcp-boundary-secret|srv\/private|mcp-boundary\.ts|\bat execute\b/i);
}
test.after(() => {
closeAuditDb();
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
if (originalApiKey === undefined) delete process.env.OMNIROUTE_API_KEY;
else process.env.OMNIROUTE_API_KEY = originalApiKey;
if (originalApiKeyId === undefined) delete process.env.OMNIROUTE_API_KEY_ID;
else process.env.OMNIROUTE_API_KEY_ID = originalApiKeyId;
if (originalInternalToken === undefined) delete process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN;
else process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN = originalInternalToken;
if (originalInternalTokenFile === undefined) {
delete process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE;
} else {
process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE = originalInternalTokenFile;
}
if (originalBaseUrl === undefined) delete process.env.OMNIROUTE_BASE_URL;
else process.env.OMNIROUTE_BASE_URL = originalBaseUrl;
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("core MCP handlers sanitize upstream bodies before public and audit boundaries", async () => {
const hostile = "Bearer mcp-fetch-boundary-secret at /srv/private/mcp-fetch-boundary.ts:9:3";
const originalFetch = globalThis.fetch;
const calledUrls: string[] = [];
globalThis.fetch = async (input) => {
calledUrls.push(String(input));
return new Response(hostile, { status: 500 });
};
try {
const handler = getRegisteredHandler(createMcpServer(), "omniroute_list_combos");
const result = await handler({ includeMetrics: false });
const publicText = result.content?.[0]?.text ?? "";
assert.equal(result.isError, true);
assert.doesNotMatch(
publicText,
/mcp-fetch-boundary-secret|srv\/private|mcp-fetch-boundary\.ts/i
);
assert.deepEqual(calledUrls, ["http://localhost:20128/api/combos"]);
const audit = await queryAuditEntries({ tool: "omniroute_list_combos", success: false });
assert.ok(audit.entries.length >= 1);
assert.doesNotMatch(
JSON.stringify(audit.entries),
/mcp-fetch-boundary-secret|srv\/private|mcp-fetch-boundary\.ts/i
);
} finally {
globalThis.fetch = originalFetch;
}
});
test("every MCP public catch uses the canonical fail-closed projector", () => {
const source = fs.readFileSync(path.join(repoRoot, "open-sse/mcp-server/server.ts"), "utf8");
assert.doesNotMatch(source, /err instanceof Error \? err\.message : String\(err\)/);
});
test("Obsidian and dynamic-skill MCP wrappers sanitize thrown errors", async () => {
const hostile = new Error(
"MCP failed access_token=mcp-boundary-secret at /srv/private/mcp-boundary.ts\n" +
" at execute (/srv/private/mcp-boundary.ts:9:3)"
);
const mutableObsidianTool = obsidianTools[0] as unknown as {
name: string;
handler: (args: unknown, extra?: unknown) => Promise<unknown>;
};
const originalObsidianHandler = mutableObsidianTool.handler;
try {
mutableObsidianTool.handler = async () => {
throw hostile;
};
const obsidianHandler = getRegisteredHandler(createMcpServer(), mutableObsidianTool.name);
assertPublicMcpError(await obsidianHandler({}, { authInfo: { scopes: ["read:obsidian"] } }));
} finally {
mutableObsidianTool.handler = originalObsidianHandler;
}
const mutableRegistry = skillRegistry as unknown as {
list: () => Array<{ name: string; description: string; enabled: boolean }>;
};
const mutableExecutor = skillExecutor as unknown as {
execute: (...args: unknown[]) => Promise<unknown>;
};
const originalList = mutableRegistry.list;
const originalExecute = mutableExecutor.execute;
try {
mutableRegistry.list = () => [
{ name: "mcp_boundary_skill", description: "boundary test", enabled: true },
];
const dynamicHandler = getRegisteredHandler(createMcpServer(), "skill_mcp_boundary_skill");
mutableExecutor.execute = async () => {
throw hostile;
};
assertPublicMcpError(
await dynamicHandler({}, { authInfo: { clientId: "test", scopes: ["execute:skills"] } })
);
} finally {
mutableRegistry.list = originalList;
mutableExecutor.execute = originalExecute;
}
});
test("skill-tool MCP wrapper uses its own fail-closed fallback for hostile thrown values", async () => {
const mutableSkillTool = Object.values(skillTools)[0] as unknown as {
name: string;
handler: (args: unknown, extra?: unknown) => Promise<unknown>;
};
const originalHandler = mutableSkillTool.handler;
const revocable = Proxy.revocable({}, {});
revocable.revoke();
try {
mutableSkillTool.handler = async () => {
throw revocable.proxy;
};
const handler = getRegisteredHandler(createMcpServer(), mutableSkillTool.name);
const result = await handler({}, { authInfo: { scopes: ["read:skills"] } });
assert.equal(result.isError, true);
assert.equal(result.content?.[0]?.text, "Error: Skill tool execution failed");
} finally {
mutableSkillTool.handler = originalHandler;
}
});

View File

@@ -0,0 +1,262 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-provider-errors-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
const originalApiKeySecret = process.env.API_KEY_SECRET;
const originalDisableBackup = process.env.DISABLE_SQLITE_AUTO_BACKUP;
const originalDisableHealthCheck = process.env.OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK;
const pluginsDir = path.join(testRoot, "plugins");
const testDataDir = path.join(testRoot, "data");
fs.mkdirSync(pluginsDir, { recursive: true });
fs.mkdirSync(testDataDir, { recursive: true });
process.env.OMNIROUTE_PLUGINS_DIR = pluginsDir;
process.env.DATA_DIR = testDataDir;
assert.notEqual(fs.realpathSync(testDataDir), "/home/diegosouzapw/.omniroute");
assert.notEqual(fs.realpathSync(pluginsDir), "/home/diegosouzapw/.omniroute/plugins");
process.env.API_KEY_SECRET = "provider-error-boundary-test-secret";
process.env.DISABLE_SQLITE_AUTO_BACKUP = "true";
process.env.OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK = "true";
// Connection tests suppress their call-log entry under node --test. This file
// exercises the real persistent boundary, so present a normal runtime identity
// before importing the route and its logging modules.
const originalArgv = process.argv;
const originalExecArgv = process.execArgv;
const originalNodeEnv = process.env.NODE_ENV;
const originalVitest = process.env.VITEST;
process.argv = [
process.execPath,
path.join(process.cwd(), "scripts/ad-hoc/omniroute-boundary-harness.mjs"),
];
process.execArgv = [];
process.env.NODE_ENV = "development";
delete process.env.VITEST;
const hostileValidationMessage =
"Jules failed access_token=jules-boundary-secret at /srv/private/validator.ts\n" +
" at probe (/srv/private/validator.ts:42:7)";
const julesValidationUrl = "https://jules.googleapis.com/v1alpha/sources";
const originalFetch = globalThis.fetch;
let validationFetchCalls = 0;
const boundaryFetch = (async (input: string | URL | Request) => {
const url =
typeof input === "string" ? input : input instanceof Request ? input.url : input.toString();
assert.equal(url, julesValidationUrl, `unexpected outbound request: ${url}`);
validationFetchCalls += 1;
return new Response(hostileValidationMessage, { status: 500 });
}) as typeof fetch;
globalThis.fetch = boundaryFetch;
const core = await import("../../../src/lib/db/core.ts");
const providersDb = await import("../../../src/lib/db/providers.ts");
const { saveCallLog, waitForCallLogSaves, closeCallLogSaves } =
await import("../../../src/lib/usage/callLogs.ts");
const { flushProxyLogsSync } = await import("../../../src/lib/proxyLogger.ts");
const { projectProviderRuntimeForPublicResponse, testSingleConnection } =
await import("../../../src/app/api/providers/[id]/test/route.ts");
// proxyFetch installs its global dispatcher while the imports above load. Put
// the deterministic stub back at the final fetch seam so this test can never
// reach Jules over the network.
globalThis.fetch = boundaryFetch;
type ArtifactRow = { artifact_relpath: string | null; error_summary: string | null };
function isRecord(value: unknown): value is Record<string, unknown> {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
function readArtifact(relativePath: string | null): Record<string, unknown> {
assert.ok(relativePath, "call log must have a persisted detail artifact");
const absolutePath = path.join(testDataDir, "call_logs", relativePath);
return JSON.parse(fs.readFileSync(absolutePath, "utf8")) as Record<string, unknown>;
}
test.after(async () => {
await closeCallLogSaves(2_000);
flushProxyLogsSync();
globalThis.fetch = originalFetch;
process.argv = originalArgv;
process.execArgv = originalExecArgv;
if (originalNodeEnv === undefined) delete process.env.NODE_ENV;
else process.env.NODE_ENV = originalNodeEnv;
if (originalVitest === undefined) delete process.env.VITEST;
else process.env.VITEST = originalVitest;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalApiKeySecret === undefined) delete process.env.API_KEY_SECRET;
else process.env.API_KEY_SECRET = originalApiKeySecret;
if (originalDisableBackup === undefined) delete process.env.DISABLE_SQLITE_AUTO_BACKUP;
else process.env.DISABLE_SQLITE_AUTO_BACKUP = originalDisableBackup;
if (originalDisableHealthCheck === undefined) {
delete process.env.OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK;
} else {
process.env.OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK = originalDisableHealthCheck;
}
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("public runtime projection omits host paths and internal error envelopes", () => {
const projected = projectProviderRuntimeForPublicResponse({
installed: true,
runnable: false,
requiresBinary: true,
reason: "not_executable",
runtimeMode: "local",
version: "v1 from /srv/private/bin/tool",
command: "/srv/private/bin/tool",
commandPath: "/srv/private/bin/tool",
settingsPath: "C:\\Users\\admin\\.config\\tool.json",
error: "access_token=runtime-secret at /srv/private/runtime.json",
diagnosis: { message: "runtime-secret at /srv/private/runtime.ts" },
});
const serialized = JSON.stringify(projected);
assert.equal(projected?.installed, true);
assert.equal(projected?.runnable, false);
assert.equal("commandPath" in (projected || {}), false);
assert.equal("settingsPath" in (projected || {}), false);
assert.equal("error" in (projected || {}), false);
assert.equal("diagnosis" in (projected || {}), false);
assert.doesNotMatch(serialized, /runtime-secret|srv\/private|C:\\\\Users/i);
});
test("connection validation projects hostile errors before public and persistent boundaries", async () => {
const connection = await providersDb.createProviderConnection({
provider: "jules",
authType: "apikey",
name: "Jules Error Boundary",
apiKey: "jules-test-key",
isActive: true,
testStatus: "active",
});
assert.ok(connection?.id);
const result = await testSingleConnection(connection.id);
assert.equal(result.valid, false);
assert.ok(validationFetchCalls > 0, "the deterministic Jules stub must handle the probe");
assert.match(String(result.error), /Jules failed/i);
assert.equal(await waitForCallLogSaves(10_000), true, "call-log write must drain");
flushProxyLogsSync();
const db = core.getDbInstance();
const providerRow = db
.prepare("SELECT last_error FROM provider_connections WHERE id = ?")
.get(connection.id) as { last_error: string | null };
const callLogRow = db
.prepare(
`SELECT error_summary, artifact_relpath
FROM call_logs
WHERE connection_id = ? AND model = 'connection-test'
ORDER BY rowid DESC LIMIT 1`
)
.get(connection.id) as ArtifactRow;
const proxyLogRow = db
.prepare(
`SELECT error
FROM proxy_logs
WHERE connection_id = ? AND provider = 'jules'
AND target_url = 'jules/connection-test'
ORDER BY rowid DESC LIMIT 1`
)
.get(connection.id) as { error: string | null };
assert.ok(callLogRow, "connection test must write call_logs");
assert.ok(proxyLogRow, "connection test must write proxy_logs");
const artifact = readArtifact(callLogRow.artifact_relpath);
const boundaries = {
publicResult: result,
providerLastError: providerRow.last_error,
callLogSummary: callLogRow.error_summary,
callLogArtifactError: artifact.error,
proxyLogError: proxyLogRow.error,
};
const leakPattern = /jules-boundary-secret|srv\/private|validator\.ts|\bat probe\b/i;
const leakingBoundaries = Object.entries(boundaries)
.filter(([, value]) => leakPattern.test(JSON.stringify(value)))
.map(([name]) => name);
assert.deepEqual(leakingBoundaries, []);
});
test("failed call logs sanitize response-body copies while successful bodies stay unchanged", async () => {
const hostileBody = {
message: "access_token=call-body-secret at /srv/private/upstream.json",
detail: "Error: api_key=call-detail-secret\n at dispatch (/srv/private/rerank.ts:7:2)",
};
const successBody = {
message: "Successful output mentions /tmp/public-example.ts and remains unchanged",
usage: { total_tokens: 4 },
};
await saveCallLog({
id: "error-body-json",
status: 502,
provider: "rerank-test",
model: "rerank-test",
responseBody: hostileBody,
pipelinePayloads: {
providerResponse: { body: hostileBody },
clientResponse: { body: hostileBody },
},
});
await saveCallLog({
id: "error-body-text",
status: 503,
provider: "rerank-test",
model: "rerank-test",
responseBody: "Bearer plaintext-body-secret at C:\\Users\\admin\\upstream.txt",
});
await saveCallLog({
id: "success-body-control",
status: 200,
provider: "rerank-test",
model: "rerank-test",
responseBody: successBody,
pipelinePayloads: {
providerResponse: { body: successBody },
clientResponse: { body: successBody },
},
});
await saveCallLog({
id: "error-body-binary",
status: 500,
provider: "rerank-test",
model: "rerank-test",
responseBody: Buffer.from([1, 2, 3, 4]),
});
assert.equal(await waitForCallLogSaves(2_000), true, "call-log writes must drain");
const db = core.getDbInstance();
const rows = db
.prepare(
`SELECT id, artifact_relpath FROM call_logs
WHERE id IN (
'error-body-json', 'error-body-text', 'success-body-control', 'error-body-binary'
)`
)
.all() as Array<{ id: string; artifact_relpath: string | null }>;
const artifacts = Object.fromEntries(
rows.map((row) => [row.id, readArtifact(row.artifact_relpath)])
) as Record<string, Record<string, unknown>>;
assert.doesNotMatch(
JSON.stringify({ json: artifacts["error-body-json"], text: artifacts["error-body-text"] }),
/call-body-secret|call-detail-secret|plaintext-body-secret|srv\/private|C:\\\\Users|\bat dispatch\b/i
);
assert.deepEqual(artifacts["success-body-control"].responseBody, successBody);
assert.equal(artifacts["error-body-binary"].responseBody, "[binary 4 bytes]");
const pipeline = artifacts["success-body-control"].pipeline;
assert.ok(isRecord(pipeline));
assert.ok(isRecord(pipeline.providerResponse));
assert.ok(isRecord(pipeline.clientResponse));
assert.deepEqual(pipeline.providerResponse.body, successBody);
assert.deepEqual(pipeline.clientResponse.body, successBody);
});

View File

@@ -0,0 +1,109 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-provider-last-error-"));
const testDataDir = path.join(testRoot, "data");
const testPluginsDir = path.join(testRoot, "plugins");
const originalEnv = {
DATA_DIR: process.env.DATA_DIR,
OMNIROUTE_PLUGINS_DIR: process.env.OMNIROUTE_PLUGINS_DIR,
API_KEY_SECRET: process.env.API_KEY_SECRET,
DISABLE_SQLITE_AUTO_BACKUP: process.env.DISABLE_SQLITE_AUTO_BACKUP,
};
fs.mkdirSync(testDataDir, { recursive: true });
fs.mkdirSync(testPluginsDir, { recursive: true });
process.env.DATA_DIR = testDataDir;
process.env.OMNIROUTE_PLUGINS_DIR = testPluginsDir;
process.env.API_KEY_SECRET = "provider-last-error-test-secret";
process.env.DISABLE_SQLITE_AUTO_BACKUP = "true";
const core = await import("../../../src/lib/db/core.ts");
const providersDb = await import("../../../src/lib/db/providers.ts");
const loggerResource = await import("../../../src/shared/utils/loggerResource.ts");
const { runAsProbe } = await import("../../../src/shared/utils/probeOrigin.ts");
const { writeTerminalStatus } = await import("../../../src/shared/utils/terminalStatus.ts");
const { markAccountUnavailable } = await import("../../../src/sse/services/auth.ts");
function restoreEnv(name: keyof typeof originalEnv): void {
const original = originalEnv[name];
if (original === undefined) delete process.env[name];
else process.env[name] = original;
}
function readLastError(connectionId: string): string | null {
const row = core
.getDbInstance()
.prepare("SELECT last_error FROM provider_connections WHERE id = ?")
.get(connectionId) as { last_error: string | null } | undefined;
return row?.last_error ?? null;
}
test.after(async () => {
core.resetDbInstance();
await loggerResource.closeSharedLoggerResource();
restoreEnv("DATA_DIR");
restoreEnv("OMNIROUTE_PLUGINS_DIR");
restoreEnv("API_KEY_SECRET");
restoreEnv("DISABLE_SQLITE_AUTO_BACKUP");
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("normal and probe failures sanitize provider_connections.lastError at the write seam", async () => {
const hostile =
"provider failed access_token=provider-last-error-secret at /srv/private/provider.ts\n" +
" at dispatch (/srv/private/provider.ts:12:4)";
const normal = await providersDb.createProviderConnection({
provider: "openai",
authType: "apikey",
name: "normal last-error boundary",
apiKey: "normal-last-error-test-key", // pragma: allowlist secret
isActive: true,
testStatus: "active",
});
const probe = await providersDb.createProviderConnection({
provider: "openai",
authType: "apikey",
name: "probe last-error boundary",
apiKey: "probe-last-error-test-key", // pragma: allowlist secret
isActive: true,
testStatus: "active",
});
const terminal = await providersDb.createProviderConnection({
provider: "openai",
authType: "apikey",
name: "terminal last-error boundary",
apiKey: "terminal-last-error-test-key", // pragma: allowlist secret
isActive: true,
testStatus: "active",
});
await markAccountUnavailable(normal.id, 500, hostile, "openai");
await runAsProbe(() => markAccountUnavailable(probe.id, 500, hostile, "openai"));
await writeTerminalStatus(
terminal.id,
{
testStatus: "banned",
isActive: false,
lastError: hostile,
lastErrorType: "forbidden",
errorCode: "403",
},
"production"
);
const persisted = {
normal: readLastError(normal.id),
probe: readLastError(probe.id),
terminal: readLastError(terminal.id),
};
assert.match(String(persisted.normal), /provider failed/i);
assert.match(String(persisted.probe), /provider failed/i);
assert.match(String(persisted.terminal), /provider failed/i);
assert.doesNotMatch(
JSON.stringify(persisted),
/provider-last-error-secret|srv\/private|provider\.ts|\bat dispatch\b/i
);
});

View File

@@ -0,0 +1,108 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const TEST_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-log-management-boundary-"));
const TEST_DATA_DIR = path.join(TEST_ROOT, "data");
const TEST_PLUGINS_DIR = path.join(TEST_ROOT, "plugins");
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
const ORIGINAL_PLUGINS_DIR = process.env.OMNIROUTE_PLUGINS_DIR;
const ORIGINAL_DISABLE_BACKUP = process.env.DISABLE_SQLITE_AUTO_BACKUP;
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
fs.mkdirSync(TEST_PLUGINS_DIR, { recursive: true });
process.env.DATA_DIR = TEST_DATA_DIR;
process.env.OMNIROUTE_PLUGINS_DIR = TEST_PLUGINS_DIR;
process.env.DISABLE_SQLITE_AUTO_BACKUP = "1";
const core = await import("../../../src/lib/db/core.ts");
const usageHistory = await import("../../../src/lib/usage/usageHistory.ts");
const logsRoute = await import("../../../src/app/api/logs/[id]/route.ts");
const usageHistoryRoute = await import("../../../src/app/api/usage/history/route.ts");
test.afterEach(() => {
usageHistory.clearPendingRequests();
});
test.after(() => {
usageHistory.clearPendingRequests();
core.resetDbInstance();
if (ORIGINAL_DATA_DIR === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = ORIGINAL_DATA_DIR;
if (ORIGINAL_PLUGINS_DIR === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = ORIGINAL_PLUGINS_DIR;
if (ORIGINAL_DISABLE_BACKUP === undefined) delete process.env.DISABLE_SQLITE_AUTO_BACKUP;
else process.env.DISABLE_SQLITE_AUTO_BACKUP = ORIGINAL_DISABLE_BACKUP;
fs.rmSync(TEST_ROOT, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
const HOSTILE =
"Bearer management-cache-secret at /srv/private/completed-request.ts:12:3\n" +
" at finalize (/srv/private/finalize.ts:4:2)";
async function readManagementDetail(id: string): Promise<Record<string, unknown>> {
const response = await logsRoute.GET(undefined as unknown as Request, { params: { id } });
assert.equal(response.status, 200);
return (await response.json()) as Record<string, unknown>;
}
function serializedDetail(detail: Record<string, unknown>): string {
return JSON.stringify(detail);
}
test("management detail sanitizes in-flight failure chunks at the endpoint boundary", async () => {
const requestId = usageHistory.trackPendingRequest("model", "provider", "conn-inflight", true);
assert.ok(requestId);
usageHistory.updatePendingRequestStreamChunks("model", "provider", "conn-inflight", {
provider: [`event: error\ndata: ${HOSTILE}\n\n`],
openai: [],
client: [],
});
const detail = await readManagementDetail(requestId);
assert.doesNotMatch(
serializedDetail(detail),
/management-cache-secret|srv\/private|completed-request\.ts|\bat finalize\b/i
);
});
test("management detail sanitizes completed error metadata and cached chunks", async () => {
const requestId = usageHistory.trackPendingRequest("model", "provider", "conn-completed", true);
assert.ok(requestId);
usageHistory.updatePendingRequestStreamChunks("model", "provider", "conn-completed", {
provider: [`data: ${JSON.stringify({ type: "error", message: HOSTILE })}\n\n`],
openai: [],
client: [],
});
assert.equal(
usageHistory.finalizePendingRequestById(requestId, { status: 502, error: HOSTILE }),
true
);
const detail = await readManagementDetail(requestId);
assert.doesNotMatch(
serializedDetail(detail),
/management-cache-secret|srv\/private|completed-request\.ts|\bat finalize\b/i
);
});
test("usage history endpoint exposes pending counters without raw request details", async () => {
const requestId = usageHistory.trackPendingRequest("model", "provider", "conn-usage", true);
assert.ok(requestId);
usageHistory.updatePendingRequestStreamChunks("model", "provider", "conn-usage", {
provider: [`event: error\ndata: ${HOSTILE}\n\n`],
openai: [],
client: [],
});
const response = await usageHistoryRoute.GET(undefined as unknown as Request);
assert.equal(response.status, 200);
const body = (await response.json()) as {
pending?: { byModel?: Record<string, number>; details?: unknown };
};
assert.equal(body.pending?.byModel?.["model (provider)"], 1);
assert.equal("details" in (body.pending ?? {}), false);
assert.doesNotMatch(JSON.stringify(body), /management-cache-secret|srv\/private/i);
});

View File

@@ -0,0 +1,91 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const TEST_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-stream-failure-code-"));
const TEST_DATA_DIR = path.join(TEST_ROOT, "data");
const TEST_PLUGINS_DIR = path.join(TEST_ROOT, "plugins");
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
const ORIGINAL_PLUGINS_DIR = process.env.OMNIROUTE_PLUGINS_DIR;
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
fs.mkdirSync(TEST_PLUGINS_DIR, { recursive: true });
process.env.DATA_DIR = TEST_DATA_DIR;
process.env.OMNIROUTE_PLUGINS_DIR = TEST_PLUGINS_DIR;
const core = await import("../../../src/lib/db/core.ts");
const failureUsage = await import("../../../open-sse/handlers/chatCore/failureUsage.ts");
const usageHistory = await import("../../../src/lib/usage/usageHistory.ts");
const { createStreamFailureFinalizers } =
await import("../../../open-sse/utils/streamFailureFinalization.ts");
test.after(() => {
core.resetDbInstance();
if (ORIGINAL_DATA_DIR === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = ORIGINAL_DATA_DIR;
if (ORIGINAL_PLUGINS_DIR === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = ORIGINAL_PLUGINS_DIR;
fs.rmSync(TEST_ROOT, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("stream failure persists only the projected public classification", () => {
const opaqueCode = "opaque-stream-code-secret-9382746";
let completionCode: string | null | undefined;
let persistedCode: string | undefined;
let classifierCode: string | undefined;
const { handleStreamFailure } = createStreamFailureFinalizers({
isFailureCompletionRecorded: () => false,
onStreamComplete: (payload) => {
completionCode = payload.errorCode;
},
persistFailureUsage: (_status, errorCode) => {
persistedCode = errorCode;
},
onStreamFailure: (failure) => {
classifierCode = failure.code;
},
});
assert.equal(
handleStreamFailure({ status: 502, message: "upstream failed", code: opaqueCode }),
true
);
assert.equal(completionCode, "bad_gateway");
assert.equal(persistedCode, "bad_gateway");
assert.equal(classifierCode, opaqueCode);
});
test("pre-response failures persist only the projected public classification", async () => {
const opaqueCode = "opaque-pre-response-code-secret-6382951";
const projectedCode = failureUsage.projectFailureUsageErrorCode({
statusCode: 502,
message: "upstream request failed",
errorCode: opaqueCode,
errorType: "opaque-pre-response-type-secret-9472013",
});
assert.equal(projectedCode, "bad_gateway");
const provider = "persistent-error-code-boundary";
await usageHistory.saveRequestUsage(
failureUsage.buildFailureUsageRecord({
provider,
model: "model",
connectionId: null,
apiKeyInfo: null,
effectiveServiceTier: "standard",
isCombo: false,
comboStrategy: null,
statusCode: 502,
errorCode: projectedCode,
latencyMs: 1,
})
);
const rows = await usageHistory.getUsageHistory({ provider });
assert.equal(rows.length, 1);
assert.equal(rows[0]?.errorCode, "bad_gateway");
assert.doesNotMatch(JSON.stringify(rows), /opaque-pre-response|6382951|9472013/);
});

View File

@@ -1,29 +1,7 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-gemini-errors-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const core = await import("../../src/lib/db/core.ts");
const { translateResponse, initState } = await import("../../open-sse/translator/index.ts");
const { FORMATS } = await import("../../open-sse/translator/formats.ts");
test.after(() => {
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
fs.rmSync(testRoot, { recursive: true, force: true });
});
import { translateResponse, initState } from "../../open-sse/translator/index.ts";
import { FORMATS } from "../../open-sse/translator/formats.ts";
test("Gemini keeps raw failure wording internal but projects response.completed.error", () => {
const state = initState(FORMATS.OPENAI_RESPONSES);

View File

@@ -0,0 +1,73 @@
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
const REPO_ROOT = fileURLToPath(new URL("../../..", import.meta.url));
const CHILD_PATH = "/usr/local/bin:/usr/bin:/bin";
const CHILD_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
type IsolatedBoundaryFixtureOptions = {
fixtureUrl: URL;
expectedTests: number;
label: string;
timeoutMs?: number;
};
export function runIsolatedBoundaryFixture({
fixtureUrl,
expectedTests,
label,
timeoutMs = 180_000,
}: IsolatedBoundaryFixtureOptions): void {
const root = mkdtempSync(join(tmpdir(), "omniroute-public-error-child-"));
const dataDir = join(root, "data");
const pluginsDir = join(root, "plugins");
mkdirSync(dataDir, { recursive: true });
mkdirSync(pluginsDir, { recursive: true });
try {
const result = spawnSync(
process.execPath,
["--import", "tsx/esm", "--test", "--test-reporter=tap", fileURLToPath(fixtureUrl)],
{
cwd: REPO_ROOT,
encoding: "utf8",
env: {
APP_LOG_TO_FILE: "false",
API_KEY_SECRET: "public-error-boundary-fixture-secret",
DATA_DIR: dataDir,
DISABLE_SQLITE_AUTO_BACKUP: "true",
LANG: "C.UTF-8",
LC_ALL: "C.UTF-8",
NODE_ENV: "test",
OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK: "true",
OMNIROUTE_PLUGINS_DIR: pluginsDir,
PATH: CHILD_PATH,
TZ: "UTC",
},
maxBuffer: CHILD_MAX_BUFFER_BYTES,
timeout: timeoutMs,
}
);
const diagnostics = [
`${label} child status=${String(result.status)} signal=${String(result.signal)}`,
result.error ? `error=${String(result.error)}` : "",
`stdout:\n${result.stdout}`,
`stderr:\n${result.stderr}`,
]
.filter(Boolean)
.join("\n");
assert.equal(result.error, undefined, diagnostics);
assert.equal(result.signal, null, diagnostics);
assert.equal(result.status, 0, diagnostics);
assert.match(result.stdout, new RegExp(`# tests ${expectedTests}(?:\\r?\\n|$)`), diagnostics);
assert.match(result.stdout, new RegExp(`# pass ${expectedTests}(?:\\r?\\n|$)`), diagnostics);
assert.match(result.stdout, /# fail 0(?:\r?\n|$)/, diagnostics);
} finally {
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
}
}

View File

@@ -1,184 +1,11 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-mcp-error-boundaries-"));
const repoRoot = fileURLToPath(new URL("../..", import.meta.url));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
const originalApiKey = process.env.OMNIROUTE_API_KEY;
const originalApiKeyId = process.env.OMNIROUTE_API_KEY_ID;
const originalInternalToken = process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN;
const originalInternalTokenFile = process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE;
const originalBaseUrl = process.env.OMNIROUTE_BASE_URL;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
process.env.OMNIROUTE_API_KEY = "mcp-boundary-test-key";
process.env.OMNIROUTE_API_KEY_ID = "mcp-boundary-test-key-id";
process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN = "mcp-boundary-internal-test-token";
process.env.OMNIROUTE_BASE_URL = "http://localhost:20128";
delete process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE;
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
import { runIsolatedBoundaryFixture } from "./helpers/runIsolatedBoundaryFixture.ts";
const { createMcpServer } = await import("../../open-sse/mcp-server/server.ts");
const { closeAuditDb, queryAuditEntries } = await import("../../open-sse/mcp-server/audit.ts");
const { obsidianTools } = await import("../../open-sse/mcp-server/tools/obsidianTools.ts");
const { skillTools } = await import("../../open-sse/mcp-server/tools/skillTools.ts");
const { skillRegistry } = await import("../../src/lib/skills/registry.ts");
const { skillExecutor } = await import("../../src/lib/skills/executor.ts");
const core = await import("../../src/lib/db/core.ts");
type McpResult = {
content?: Array<{ type: string; text: string }>;
isError?: boolean;
};
type RegisteredTool = {
handler: (args: unknown, extra?: unknown) => Promise<McpResult>;
};
function getRegisteredHandler(server: unknown, toolName: string): RegisteredTool["handler"] {
const registry = (server as { _registeredTools?: Record<string, RegisteredTool> })
._registeredTools;
assert.ok(registry, "McpServer should expose _registeredTools");
const tool = registry[toolName];
assert.ok(tool, `${toolName} must be registered`);
return tool.handler;
}
function assertPublicMcpError(result: McpResult): void {
const text = result.content?.[0]?.text ?? "";
assert.equal(result.isError, true);
assert.match(text, /Error:/);
assert.doesNotMatch(text, /mcp-boundary-secret|srv\/private|mcp-boundary\.ts|\bat execute\b/i);
}
test.after(() => {
closeAuditDb();
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
if (originalApiKey === undefined) delete process.env.OMNIROUTE_API_KEY;
else process.env.OMNIROUTE_API_KEY = originalApiKey;
if (originalApiKeyId === undefined) delete process.env.OMNIROUTE_API_KEY_ID;
else process.env.OMNIROUTE_API_KEY_ID = originalApiKeyId;
if (originalInternalToken === undefined) delete process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN;
else process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN = originalInternalToken;
if (originalInternalTokenFile === undefined) {
delete process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE;
} else {
process.env.OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE = originalInternalTokenFile;
}
if (originalBaseUrl === undefined) delete process.env.OMNIROUTE_BASE_URL;
else process.env.OMNIROUTE_BASE_URL = originalBaseUrl;
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("core MCP handlers sanitize upstream bodies before public and audit boundaries", async () => {
const hostile = "Bearer mcp-fetch-boundary-secret at /srv/private/mcp-fetch-boundary.ts:9:3";
const originalFetch = globalThis.fetch;
const calledUrls: string[] = [];
globalThis.fetch = async (input) => {
calledUrls.push(String(input));
return new Response(hostile, { status: 500 });
};
try {
const handler = getRegisteredHandler(createMcpServer(), "omniroute_list_combos");
const result = await handler({ includeMetrics: false });
const publicText = result.content?.[0]?.text ?? "";
assert.equal(result.isError, true);
assert.doesNotMatch(
publicText,
/mcp-fetch-boundary-secret|srv\/private|mcp-fetch-boundary\.ts/i
);
assert.deepEqual(calledUrls, ["http://localhost:20128/api/combos"]);
const audit = await queryAuditEntries({ tool: "omniroute_list_combos", success: false });
assert.ok(audit.entries.length >= 1);
assert.doesNotMatch(
JSON.stringify(audit.entries),
/mcp-fetch-boundary-secret|srv\/private|mcp-fetch-boundary\.ts/i
);
} finally {
globalThis.fetch = originalFetch;
}
});
test("every MCP public catch uses the canonical fail-closed projector", () => {
const source = fs.readFileSync(path.join(repoRoot, "open-sse/mcp-server/server.ts"), "utf8");
assert.doesNotMatch(source, /err instanceof Error \? err\.message : String\(err\)/);
});
test("Obsidian and dynamic-skill MCP wrappers sanitize thrown errors", async () => {
const hostile = new Error(
"MCP failed access_token=mcp-boundary-secret at /srv/private/mcp-boundary.ts\n" +
" at execute (/srv/private/mcp-boundary.ts:9:3)"
);
const mutableObsidianTool = obsidianTools[0] as unknown as {
name: string;
handler: (args: unknown, extra?: unknown) => Promise<unknown>;
};
const originalObsidianHandler = mutableObsidianTool.handler;
try {
mutableObsidianTool.handler = async () => {
throw hostile;
};
const obsidianHandler = getRegisteredHandler(createMcpServer(), mutableObsidianTool.name);
assertPublicMcpError(await obsidianHandler({}, { authInfo: { scopes: ["read:obsidian"] } }));
} finally {
mutableObsidianTool.handler = originalObsidianHandler;
}
const mutableRegistry = skillRegistry as unknown as {
list: () => Array<{ name: string; description: string; enabled: boolean }>;
};
const mutableExecutor = skillExecutor as unknown as {
execute: (...args: unknown[]) => Promise<unknown>;
};
const originalList = mutableRegistry.list;
const originalExecute = mutableExecutor.execute;
try {
mutableRegistry.list = () => [
{ name: "mcp_boundary_skill", description: "boundary test", enabled: true },
];
const dynamicHandler = getRegisteredHandler(createMcpServer(), "skill_mcp_boundary_skill");
mutableExecutor.execute = async () => {
throw hostile;
};
assertPublicMcpError(
await dynamicHandler({}, { authInfo: { clientId: "test", scopes: ["execute:skills"] } })
);
} finally {
mutableRegistry.list = originalList;
mutableExecutor.execute = originalExecute;
}
});
test("skill-tool MCP wrapper uses its own fail-closed fallback for hostile thrown values", async () => {
const mutableSkillTool = Object.values(skillTools)[0] as unknown as {
name: string;
handler: (args: unknown, extra?: unknown) => Promise<unknown>;
};
const originalHandler = mutableSkillTool.handler;
const revocable = Proxy.revocable({}, {});
revocable.revoke();
try {
mutableSkillTool.handler = async () => {
throw revocable.proxy;
};
const handler = getRegisteredHandler(createMcpServer(), mutableSkillTool.name);
const result = await handler({}, { authInfo: { scopes: ["read:skills"] } });
assert.equal(result.isError, true);
assert.equal(result.content?.[0]?.text, "Error: Skill tool execution failed");
} finally {
mutableSkillTool.handler = originalHandler;
}
test("MCP public error boundaries pass in an isolated child process", () => {
runIsolatedBoundaryFixture({
fixtureUrl: new URL("./fixtures/mcp-public-error-boundaries.fixture.ts", import.meta.url),
expectedTests: 4,
label: "MCP public error boundaries",
});
});

View File

@@ -1,18 +1,6 @@
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-moderations-handler-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const core = await import("../../src/lib/db/core.ts");
const { handleModeration } = await import("../../open-sse/handlers/moderations.ts");
const { MODERATION_PROVIDERS, getModerationProvider, parseModerationModel } =
await import("../../open-sse/config/moderationRegistry.ts");
@@ -23,15 +11,6 @@ test.afterEach(() => {
globalThis.fetch = originalFetch;
});
test.after(() => {
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("MODERATION_PROVIDERS registers mistral with the Mistral moderations base URL", () => {
const provider = getModerationProvider("mistral");
assert.ok(provider);

View File

@@ -1,28 +1,6 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-ocr-handler-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const core = await import("../../src/lib/db/core.ts");
const { handleOcr } = await import("../../open-sse/handlers/ocr.ts");
test.after(() => {
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
import { handleOcr } from "../../open-sse/handlers/ocr.ts";
function fetchStub(
script: Array<{ status: number; headers?: Record<string, string>; json?: unknown }>

View File

@@ -1,262 +1,14 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-provider-errors-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
const originalApiKeySecret = process.env.API_KEY_SECRET;
const originalDisableBackup = process.env.DISABLE_SQLITE_AUTO_BACKUP;
const originalDisableHealthCheck = process.env.OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK;
const pluginsDir = path.join(testRoot, "plugins");
const testDataDir = path.join(testRoot, "data");
fs.mkdirSync(pluginsDir, { recursive: true });
fs.mkdirSync(testDataDir, { recursive: true });
process.env.OMNIROUTE_PLUGINS_DIR = pluginsDir;
process.env.DATA_DIR = testDataDir;
assert.notEqual(fs.realpathSync(testDataDir), "/home/diegosouzapw/.omniroute");
assert.notEqual(fs.realpathSync(pluginsDir), "/home/diegosouzapw/.omniroute/plugins");
import { runIsolatedBoundaryFixture } from "./helpers/runIsolatedBoundaryFixture.ts";
process.env.API_KEY_SECRET = "provider-error-boundary-test-secret";
process.env.DISABLE_SQLITE_AUTO_BACKUP = "true";
process.env.OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK = "true";
// Connection tests suppress their call-log entry under node --test. This file
// exercises the real persistent boundary, so present a normal runtime identity
// before importing the route and its logging modules.
const originalArgv = process.argv;
const originalExecArgv = process.execArgv;
const originalNodeEnv = process.env.NODE_ENV;
const originalVitest = process.env.VITEST;
process.argv = [
process.execPath,
path.join(process.cwd(), "scripts/ad-hoc/omniroute-boundary-harness.mjs"),
];
process.execArgv = [];
process.env.NODE_ENV = "development";
delete process.env.VITEST;
const hostileValidationMessage =
"Jules failed access_token=jules-boundary-secret at /srv/private/validator.ts\n" +
" at probe (/srv/private/validator.ts:42:7)";
const julesValidationUrl = "https://jules.googleapis.com/v1alpha/sources";
const originalFetch = globalThis.fetch;
let validationFetchCalls = 0;
const boundaryFetch = (async (input: string | URL | Request) => {
const url =
typeof input === "string" ? input : input instanceof Request ? input.url : input.toString();
assert.equal(url, julesValidationUrl, `unexpected outbound request: ${url}`);
validationFetchCalls += 1;
return new Response(hostileValidationMessage, { status: 500 });
}) as typeof fetch;
globalThis.fetch = boundaryFetch;
const core = await import("../../src/lib/db/core.ts");
const providersDb = await import("../../src/lib/db/providers.ts");
const { saveCallLog, waitForCallLogSaves, closeCallLogSaves } =
await import("../../src/lib/usage/callLogs.ts");
const { flushProxyLogsSync } = await import("../../src/lib/proxyLogger.ts");
const { projectProviderRuntimeForPublicResponse, testSingleConnection } =
await import("../../src/app/api/providers/[id]/test/route.ts");
// proxyFetch installs its global dispatcher while the imports above load. Put
// the deterministic stub back at the final fetch seam so this test can never
// reach Jules over the network.
globalThis.fetch = boundaryFetch;
type ArtifactRow = { artifact_relpath: string | null; error_summary: string | null };
function isRecord(value: unknown): value is Record<string, unknown> {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
function readArtifact(relativePath: string | null): Record<string, unknown> {
assert.ok(relativePath, "call log must have a persisted detail artifact");
const absolutePath = path.join(testDataDir, "call_logs", relativePath);
return JSON.parse(fs.readFileSync(absolutePath, "utf8")) as Record<string, unknown>;
}
test.after(async () => {
await closeCallLogSaves(2_000);
flushProxyLogsSync();
globalThis.fetch = originalFetch;
process.argv = originalArgv;
process.execArgv = originalExecArgv;
if (originalNodeEnv === undefined) delete process.env.NODE_ENV;
else process.env.NODE_ENV = originalNodeEnv;
if (originalVitest === undefined) delete process.env.VITEST;
else process.env.VITEST = originalVitest;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalApiKeySecret === undefined) delete process.env.API_KEY_SECRET;
else process.env.API_KEY_SECRET = originalApiKeySecret;
if (originalDisableBackup === undefined) delete process.env.DISABLE_SQLITE_AUTO_BACKUP;
else process.env.DISABLE_SQLITE_AUTO_BACKUP = originalDisableBackup;
if (originalDisableHealthCheck === undefined) {
delete process.env.OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK;
} else {
process.env.OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK = originalDisableHealthCheck;
}
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("public runtime projection omits host paths and internal error envelopes", () => {
const projected = projectProviderRuntimeForPublicResponse({
installed: true,
runnable: false,
requiresBinary: true,
reason: "not_executable",
runtimeMode: "local",
version: "v1 from /srv/private/bin/tool",
command: "/srv/private/bin/tool",
commandPath: "/srv/private/bin/tool",
settingsPath: "C:\\Users\\admin\\.config\\tool.json",
error: "access_token=runtime-secret at /srv/private/runtime.json",
diagnosis: { message: "runtime-secret at /srv/private/runtime.ts" },
test("provider connection error boundaries pass in an isolated child process", () => {
runIsolatedBoundaryFixture({
fixtureUrl: new URL(
"./fixtures/provider-connection-test-error-boundaries.fixture.ts",
import.meta.url
),
expectedTests: 3,
label: "provider connection error boundaries",
});
const serialized = JSON.stringify(projected);
assert.equal(projected?.installed, true);
assert.equal(projected?.runnable, false);
assert.equal("commandPath" in (projected || {}), false);
assert.equal("settingsPath" in (projected || {}), false);
assert.equal("error" in (projected || {}), false);
assert.equal("diagnosis" in (projected || {}), false);
assert.doesNotMatch(serialized, /runtime-secret|srv\/private|C:\\\\Users/i);
});
test("connection validation projects hostile errors before public and persistent boundaries", async () => {
const connection = await providersDb.createProviderConnection({
provider: "jules",
authType: "apikey",
name: "Jules Error Boundary",
apiKey: "jules-test-key",
isActive: true,
testStatus: "active",
});
assert.ok(connection?.id);
const result = await testSingleConnection(connection.id);
assert.equal(result.valid, false);
assert.ok(validationFetchCalls > 0, "the deterministic Jules stub must handle the probe");
assert.match(String(result.error), /Jules failed/i);
assert.equal(await waitForCallLogSaves(10_000), true, "call-log write must drain");
flushProxyLogsSync();
const db = core.getDbInstance();
const providerRow = db
.prepare("SELECT last_error FROM provider_connections WHERE id = ?")
.get(connection.id) as { last_error: string | null };
const callLogRow = db
.prepare(
`SELECT error_summary, artifact_relpath
FROM call_logs
WHERE connection_id = ? AND model = 'connection-test'
ORDER BY rowid DESC LIMIT 1`
)
.get(connection.id) as ArtifactRow;
const proxyLogRow = db
.prepare(
`SELECT error
FROM proxy_logs
WHERE connection_id = ? AND provider = 'jules'
AND target_url = 'jules/connection-test'
ORDER BY rowid DESC LIMIT 1`
)
.get(connection.id) as { error: string | null };
assert.ok(callLogRow, "connection test must write call_logs");
assert.ok(proxyLogRow, "connection test must write proxy_logs");
const artifact = readArtifact(callLogRow.artifact_relpath);
const boundaries = {
publicResult: result,
providerLastError: providerRow.last_error,
callLogSummary: callLogRow.error_summary,
callLogArtifactError: artifact.error,
proxyLogError: proxyLogRow.error,
};
const leakPattern = /jules-boundary-secret|srv\/private|validator\.ts|\bat probe\b/i;
const leakingBoundaries = Object.entries(boundaries)
.filter(([, value]) => leakPattern.test(JSON.stringify(value)))
.map(([name]) => name);
assert.deepEqual(leakingBoundaries, []);
});
test("failed call logs sanitize response-body copies while successful bodies stay unchanged", async () => {
const hostileBody = {
message: "access_token=call-body-secret at /srv/private/upstream.json",
detail: "Error: api_key=call-detail-secret\n at dispatch (/srv/private/rerank.ts:7:2)",
};
const successBody = {
message: "Successful output mentions /tmp/public-example.ts and remains unchanged",
usage: { total_tokens: 4 },
};
await saveCallLog({
id: "error-body-json",
status: 502,
provider: "rerank-test",
model: "rerank-test",
responseBody: hostileBody,
pipelinePayloads: {
providerResponse: { body: hostileBody },
clientResponse: { body: hostileBody },
},
});
await saveCallLog({
id: "error-body-text",
status: 503,
provider: "rerank-test",
model: "rerank-test",
responseBody: "Bearer plaintext-body-secret at C:\\Users\\admin\\upstream.txt",
});
await saveCallLog({
id: "success-body-control",
status: 200,
provider: "rerank-test",
model: "rerank-test",
responseBody: successBody,
pipelinePayloads: {
providerResponse: { body: successBody },
clientResponse: { body: successBody },
},
});
await saveCallLog({
id: "error-body-binary",
status: 500,
provider: "rerank-test",
model: "rerank-test",
responseBody: Buffer.from([1, 2, 3, 4]),
});
assert.equal(await waitForCallLogSaves(2_000), true, "call-log writes must drain");
const db = core.getDbInstance();
const rows = db
.prepare(
`SELECT id, artifact_relpath FROM call_logs
WHERE id IN (
'error-body-json', 'error-body-text', 'success-body-control', 'error-body-binary'
)`
)
.all() as Array<{ id: string; artifact_relpath: string | null }>;
const artifacts = Object.fromEntries(
rows.map((row) => [row.id, readArtifact(row.artifact_relpath)])
) as Record<string, Record<string, unknown>>;
assert.doesNotMatch(
JSON.stringify({ json: artifacts["error-body-json"], text: artifacts["error-body-text"] }),
/call-body-secret|call-detail-secret|plaintext-body-secret|srv\/private|C:\\\\Users|\bat dispatch\b/i
);
assert.deepEqual(artifacts["success-body-control"].responseBody, successBody);
assert.equal(artifacts["error-body-binary"].responseBody, "[binary 4 bytes]");
const pipeline = artifacts["success-body-control"].pipeline;
assert.ok(isRecord(pipeline));
assert.ok(isRecord(pipeline.providerResponse));
assert.ok(isRecord(pipeline.clientResponse));
assert.deepEqual(pipeline.providerResponse.body, successBody);
assert.deepEqual(pipeline.clientResponse.body, successBody);
});

View File

@@ -1,109 +1,11 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-provider-last-error-"));
const testDataDir = path.join(testRoot, "data");
const testPluginsDir = path.join(testRoot, "plugins");
const originalEnv = {
DATA_DIR: process.env.DATA_DIR,
OMNIROUTE_PLUGINS_DIR: process.env.OMNIROUTE_PLUGINS_DIR,
API_KEY_SECRET: process.env.API_KEY_SECRET,
DISABLE_SQLITE_AUTO_BACKUP: process.env.DISABLE_SQLITE_AUTO_BACKUP,
};
fs.mkdirSync(testDataDir, { recursive: true });
fs.mkdirSync(testPluginsDir, { recursive: true });
process.env.DATA_DIR = testDataDir;
process.env.OMNIROUTE_PLUGINS_DIR = testPluginsDir;
process.env.API_KEY_SECRET = "provider-last-error-test-secret";
process.env.DISABLE_SQLITE_AUTO_BACKUP = "true";
import { runIsolatedBoundaryFixture } from "./helpers/runIsolatedBoundaryFixture.ts";
const core = await import("../../src/lib/db/core.ts");
const providersDb = await import("../../src/lib/db/providers.ts");
const loggerResource = await import("../../src/shared/utils/loggerResource.ts");
const { runAsProbe } = await import("../../src/shared/utils/probeOrigin.ts");
const { writeTerminalStatus } = await import("../../src/shared/utils/terminalStatus.ts");
const { markAccountUnavailable } = await import("../../src/sse/services/auth.ts");
function restoreEnv(name: keyof typeof originalEnv): void {
const original = originalEnv[name];
if (original === undefined) delete process.env[name];
else process.env[name] = original;
}
function readLastError(connectionId: string): string | null {
const row = core
.getDbInstance()
.prepare("SELECT last_error FROM provider_connections WHERE id = ?")
.get(connectionId) as { last_error: string | null } | undefined;
return row?.last_error ?? null;
}
test.after(async () => {
core.resetDbInstance();
await loggerResource.closeSharedLoggerResource();
restoreEnv("DATA_DIR");
restoreEnv("OMNIROUTE_PLUGINS_DIR");
restoreEnv("API_KEY_SECRET");
restoreEnv("DISABLE_SQLITE_AUTO_BACKUP");
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("normal and probe failures sanitize provider_connections.lastError at the write seam", async () => {
const hostile =
"provider failed access_token=provider-last-error-secret at /srv/private/provider.ts\n" +
" at dispatch (/srv/private/provider.ts:12:4)";
const normal = await providersDb.createProviderConnection({
provider: "openai",
authType: "apikey",
name: "normal last-error boundary",
apiKey: "normal-last-error-test-key", // pragma: allowlist secret
isActive: true,
testStatus: "active",
test("provider last-error persistence passes in an isolated child process", () => {
runIsolatedBoundaryFixture({
fixtureUrl: new URL("./fixtures/provider-last-error-sanitization.fixture.ts", import.meta.url),
expectedTests: 1,
label: "provider last-error persistence",
});
const probe = await providersDb.createProviderConnection({
provider: "openai",
authType: "apikey",
name: "probe last-error boundary",
apiKey: "probe-last-error-test-key", // pragma: allowlist secret
isActive: true,
testStatus: "active",
});
const terminal = await providersDb.createProviderConnection({
provider: "openai",
authType: "apikey",
name: "terminal last-error boundary",
apiKey: "terminal-last-error-test-key", // pragma: allowlist secret
isActive: true,
testStatus: "active",
});
await markAccountUnavailable(normal.id, 500, hostile, "openai");
await runAsProbe(() => markAccountUnavailable(probe.id, 500, hostile, "openai"));
await writeTerminalStatus(
terminal.id,
{
testStatus: "banned",
isActive: false,
lastError: hostile,
lastErrorType: "forbidden",
errorCode: "403",
},
"production"
);
const persisted = {
normal: readLastError(normal.id),
probe: readLastError(probe.id),
terminal: readLastError(terminal.id),
};
assert.match(String(persisted.normal), /provider failed/i);
assert.match(String(persisted.probe), /provider failed/i);
assert.match(String(persisted.terminal), /provider failed/i);
assert.doesNotMatch(
JSON.stringify(persisted),
/provider-last-error-secret|srv\/private|provider\.ts|\bat dispatch\b/i
);
});

View File

@@ -1,32 +1,10 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const TEST_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-provider-validation-errors-"));
const TEST_DATA_DIR = path.join(TEST_ROOT, "data");
const TEST_PLUGINS_DIR = path.join(TEST_ROOT, "plugins");
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
const ORIGINAL_PLUGINS_DIR = process.env.OMNIROUTE_PLUGINS_DIR;
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
fs.mkdirSync(TEST_PLUGINS_DIR, { recursive: true });
process.env.DATA_DIR = TEST_DATA_DIR;
process.env.OMNIROUTE_PLUGINS_DIR = TEST_PLUGINS_DIR;
const core = await import("../../src/lib/db/core.ts");
const { projectProviderValidationResultForPublicResponse, toValidationErrorResult } =
await import("../../src/lib/providers/validation/transport.ts");
test.after(() => {
core.resetDbInstance();
if (ORIGINAL_DATA_DIR === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = ORIGINAL_DATA_DIR;
if (ORIGINAL_PLUGINS_DIR === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = ORIGINAL_PLUGINS_DIR;
fs.rmSync(TEST_ROOT, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
import {
projectProviderValidationResultForPublicResponse,
toValidationErrorResult,
} from "../../src/lib/providers/validation/transport.ts";
test("provider validation sanitizes thrown error details", () => {
const result = toValidationErrorResult(

View File

@@ -1,108 +1,11 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const TEST_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-log-management-boundary-"));
const TEST_DATA_DIR = path.join(TEST_ROOT, "data");
const TEST_PLUGINS_DIR = path.join(TEST_ROOT, "plugins");
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
const ORIGINAL_PLUGINS_DIR = process.env.OMNIROUTE_PLUGINS_DIR;
const ORIGINAL_DISABLE_BACKUP = process.env.DISABLE_SQLITE_AUTO_BACKUP;
import { runIsolatedBoundaryFixture } from "./helpers/runIsolatedBoundaryFixture.ts";
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
fs.mkdirSync(TEST_PLUGINS_DIR, { recursive: true });
process.env.DATA_DIR = TEST_DATA_DIR;
process.env.OMNIROUTE_PLUGINS_DIR = TEST_PLUGINS_DIR;
process.env.DISABLE_SQLITE_AUTO_BACKUP = "1";
const core = await import("../../src/lib/db/core.ts");
const usageHistory = await import("../../src/lib/usage/usageHistory.ts");
const logsRoute = await import("../../src/app/api/logs/[id]/route.ts");
const usageHistoryRoute = await import("../../src/app/api/usage/history/route.ts");
test.afterEach(() => {
usageHistory.clearPendingRequests();
});
test.after(() => {
usageHistory.clearPendingRequests();
core.resetDbInstance();
if (ORIGINAL_DATA_DIR === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = ORIGINAL_DATA_DIR;
if (ORIGINAL_PLUGINS_DIR === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = ORIGINAL_PLUGINS_DIR;
if (ORIGINAL_DISABLE_BACKUP === undefined) delete process.env.DISABLE_SQLITE_AUTO_BACKUP;
else process.env.DISABLE_SQLITE_AUTO_BACKUP = ORIGINAL_DISABLE_BACKUP;
fs.rmSync(TEST_ROOT, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
const HOSTILE =
"Bearer management-cache-secret at /srv/private/completed-request.ts:12:3\n" +
" at finalize (/srv/private/finalize.ts:4:2)";
async function readManagementDetail(id: string): Promise<Record<string, unknown>> {
const response = await logsRoute.GET(undefined as unknown as Request, { params: { id } });
assert.equal(response.status, 200);
return (await response.json()) as Record<string, unknown>;
}
function serializedDetail(detail: Record<string, unknown>): string {
return JSON.stringify(detail);
}
test("management detail sanitizes in-flight failure chunks at the endpoint boundary", async () => {
const requestId = usageHistory.trackPendingRequest("model", "provider", "conn-inflight", true);
assert.ok(requestId);
usageHistory.updatePendingRequestStreamChunks("model", "provider", "conn-inflight", {
provider: [`event: error\ndata: ${HOSTILE}\n\n`],
openai: [],
client: [],
test("request-log management boundaries pass in an isolated child process", () => {
runIsolatedBoundaryFixture({
fixtureUrl: new URL("./fixtures/request-log-management-boundary.fixture.ts", import.meta.url),
expectedTests: 3,
label: "request-log management boundaries",
});
const detail = await readManagementDetail(requestId);
assert.doesNotMatch(
serializedDetail(detail),
/management-cache-secret|srv\/private|completed-request\.ts|\bat finalize\b/i
);
});
test("management detail sanitizes completed error metadata and cached chunks", async () => {
const requestId = usageHistory.trackPendingRequest("model", "provider", "conn-completed", true);
assert.ok(requestId);
usageHistory.updatePendingRequestStreamChunks("model", "provider", "conn-completed", {
provider: [`data: ${JSON.stringify({ type: "error", message: HOSTILE })}\n\n`],
openai: [],
client: [],
});
assert.equal(
usageHistory.finalizePendingRequestById(requestId, { status: 502, error: HOSTILE }),
true
);
const detail = await readManagementDetail(requestId);
assert.doesNotMatch(
serializedDetail(detail),
/management-cache-secret|srv\/private|completed-request\.ts|\bat finalize\b/i
);
});
test("usage history endpoint exposes pending counters without raw request details", async () => {
const requestId = usageHistory.trackPendingRequest("model", "provider", "conn-usage", true);
assert.ok(requestId);
usageHistory.updatePendingRequestStreamChunks("model", "provider", "conn-usage", {
provider: [`event: error\ndata: ${HOSTILE}\n\n`],
openai: [],
client: [],
});
const response = await usageHistoryRoute.GET(undefined as unknown as Request);
assert.equal(response.status, 200);
const body = (await response.json()) as {
pending?: { byModel?: Record<string, number>; details?: unknown };
};
assert.equal(body.pending?.byModel?.["model (provider)"], 1);
assert.equal("details" in (body.pending ?? {}), false);
assert.doesNotMatch(JSON.stringify(body), /management-cache-secret|srv\/private/i);
});

View File

@@ -1,19 +1,6 @@
import { protectPipelinePayloads } from "../../src/lib/usage/callLogs/format.ts";
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-request-log-payloads-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const core = await import("../../src/lib/db/core.ts");
const { protectPipelinePayloads } = await import("../../src/lib/usage/callLogs/format.ts");
const {
normalizePayloadForLog,
@@ -29,15 +16,6 @@ const {
} = await import("../../open-sse/utils/streamPayloadCollector.ts");
const { FORMATS } = await import("../../open-sse/translator/formats.ts");
test.after(() => {
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("normalizes JSON strings before log protection and redacts sensitive keys", () => {
const protectedPayload = protectPayloadForLog(
JSON.stringify({

View File

@@ -1,91 +1,14 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const TEST_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-stream-failure-code-"));
const TEST_DATA_DIR = path.join(TEST_ROOT, "data");
const TEST_PLUGINS_DIR = path.join(TEST_ROOT, "plugins");
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
const ORIGINAL_PLUGINS_DIR = process.env.OMNIROUTE_PLUGINS_DIR;
import { runIsolatedBoundaryFixture } from "./helpers/runIsolatedBoundaryFixture.ts";
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
fs.mkdirSync(TEST_PLUGINS_DIR, { recursive: true });
process.env.DATA_DIR = TEST_DATA_DIR;
process.env.OMNIROUTE_PLUGINS_DIR = TEST_PLUGINS_DIR;
const core = await import("../../src/lib/db/core.ts");
const failureUsage = await import("../../open-sse/handlers/chatCore/failureUsage.ts");
const usageHistory = await import("../../src/lib/usage/usageHistory.ts");
const { createStreamFailureFinalizers } =
await import("../../open-sse/utils/streamFailureFinalization.ts");
test.after(() => {
core.resetDbInstance();
if (ORIGINAL_DATA_DIR === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = ORIGINAL_DATA_DIR;
if (ORIGINAL_PLUGINS_DIR === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = ORIGINAL_PLUGINS_DIR;
fs.rmSync(TEST_ROOT, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("stream failure persists only the projected public classification", () => {
const opaqueCode = "opaque-stream-code-secret-9382746";
let completionCode: string | null | undefined;
let persistedCode: string | undefined;
let classifierCode: string | undefined;
const { handleStreamFailure } = createStreamFailureFinalizers({
isFailureCompletionRecorded: () => false,
onStreamComplete: (payload) => {
completionCode = payload.errorCode;
},
persistFailureUsage: (_status, errorCode) => {
persistedCode = errorCode;
},
onStreamFailure: (failure) => {
classifierCode = failure.code;
},
test("stream failure persistence boundaries pass in an isolated child process", () => {
runIsolatedBoundaryFixture({
fixtureUrl: new URL(
"./fixtures/stream-failure-persistent-classification.fixture.ts",
import.meta.url
),
expectedTests: 2,
label: "stream failure persistence boundaries",
});
assert.equal(
handleStreamFailure({ status: 502, message: "upstream failed", code: opaqueCode }),
true
);
assert.equal(completionCode, "bad_gateway");
assert.equal(persistedCode, "bad_gateway");
assert.equal(classifierCode, opaqueCode);
});
test("pre-response failures persist only the projected public classification", async () => {
const opaqueCode = "opaque-pre-response-code-secret-6382951";
const projectedCode = failureUsage.projectFailureUsageErrorCode({
statusCode: 502,
message: "upstream request failed",
errorCode: opaqueCode,
errorType: "opaque-pre-response-type-secret-9472013",
});
assert.equal(projectedCode, "bad_gateway");
const provider = "persistent-error-code-boundary";
await usageHistory.saveRequestUsage(
failureUsage.buildFailureUsageRecord({
provider,
model: "model",
connectionId: null,
apiKeyInfo: null,
effectiveServiceTier: "standard",
isCombo: false,
comboStrategy: null,
statusCode: 502,
errorCode: projectedCode,
latencyMs: 1,
})
);
const rows = await usageHistory.getUsageHistory({ provider });
assert.equal(rows.length, 1);
assert.equal(rows[0]?.errorCode, "bad_gateway");
assert.doesNotMatch(JSON.stringify(rows), /opaque-pre-response|6382951|9472013/);
});

View File

@@ -1,29 +1,7 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-stream-errors-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const core = await import("../../src/lib/db/core.ts");
const { createSSEStream } = await import("../../open-sse/utils/stream.ts");
const { FORMATS } = await import("../../open-sse/translator/formats.ts");
test.after(() => {
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
fs.rmSync(testRoot, { recursive: true, force: true });
});
import { createSSEStream } from "../../open-sse/utils/stream.ts";
import { FORMATS } from "../../open-sse/translator/formats.ts";
type Failure = { status: number; message: string; code?: string; type?: string };

View File

@@ -1,30 +1,10 @@
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-upstream-passthrough-"));
const originalDataDir = process.env.DATA_DIR;
const originalPluginsDir = process.env.OMNIROUTE_PLUGINS_DIR;
process.env.DATA_DIR = path.join(testRoot, "data");
process.env.OMNIROUTE_PLUGINS_DIR = path.join(testRoot, "plugins");
fs.mkdirSync(process.env.DATA_DIR, { recursive: true });
fs.mkdirSync(process.env.OMNIROUTE_PLUGINS_DIR, { recursive: true });
const core = await import("../../src/lib/db/core.ts");
const { shouldPassthroughUpstreamError, buildPassthroughErrorResponse } =
await import("../../open-sse/utils/upstreamErrorPassthrough.ts");
const { buildSanitizedUpstreamErrorResponse } =
await import("../../open-sse/utils/upstreamErrorResponse.ts");
test.after(() => {
core.resetDbInstance();
if (originalDataDir === undefined) delete process.env.DATA_DIR;
else process.env.DATA_DIR = originalDataDir;
if (originalPluginsDir === undefined) delete process.env.OMNIROUTE_PLUGINS_DIR;
else process.env.OMNIROUTE_PLUGINS_DIR = originalPluginsDir;
fs.rmSync(testRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
import {
shouldPassthroughUpstreamError,
buildPassthroughErrorResponse,
} from "../../open-sse/utils/upstreamErrorPassthrough.ts";
import { buildSanitizedUpstreamErrorResponse } from "../../open-sse/utils/upstreamErrorResponse.ts";
test("upstream error passthrough", async (t) => {
await t.test("4xx com corpo JSON de erro do provider é elegível", () => {