fix: secure assistant generation telemetry
This commit is contained in:
1 parent
04520cf67c
commit
8bb0ddef42
11 files changed
+181
-10
No files matched your search
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
vi.mock("@homarr/common/env", () => ({
|
||||
env: { SECRET_ENCRYPTION_KEY: "a".repeat(64) },
|
||||
}));
|
||||
|
||||
import {
|
||||
createAssistantGenerationAccessToken,
|
||||
verifyAssistantGenerationAccessToken,
|
||||
} from "../assistant-generation-access";
|
||||
|
||||
describe("assistant generation access token", () => {
|
||||
const input = {
|
||||
userId: "user-1",
|
||||
threadId: "thread-1",
|
||||
generationId: "gen-example",
|
||||
};
|
||||
|
||||
test("binds a generation to its user and conversation", () => {
|
||||
const accessToken = createAssistantGenerationAccessToken(input);
|
||||
|
||||
expect(accessToken).toMatch(/^[A-Za-z0-9_-]{43}$/);
|
||||
expect(verifyAssistantGenerationAccessToken(input, accessToken)).toBe(true);
|
||||
expect(verifyAssistantGenerationAccessToken({ ...input, userId: "user-2" }, accessToken)).toBe(false);
|
||||
expect(verifyAssistantGenerationAccessToken({ ...input, threadId: "thread-2" }, accessToken)).toBe(false);
|
||||
expect(verifyAssistantGenerationAccessToken({ ...input, generationId: "gen-other" }, accessToken)).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,13 @@
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
|
||||
|
||||
vi.mock("@homarr/core/infrastructure/http", () => ({ fetchWithTrustedCertificatesAsync: vi.fn() }));
|
||||
|
||||
import { parseOpenRouterGenerationTelemetry } from "../assistant-generation-telemetry";
|
||||
import {
|
||||
fetchOpenRouterGenerationTelemetryAsync,
|
||||
parseOpenRouterGenerationTelemetry,
|
||||
} from "../assistant-generation-telemetry";
|
||||
|
||||
describe("parseOpenRouterGenerationTelemetry", () => {
|
||||
test("uses provider-native tokens for context and throughput", () => {
|
||||
@@ -63,4 +68,38 @@ describe("parseOpenRouterGenerationTelemetry", () => {
|
||||
expect(parseOpenRouterGenerationTelemetry({ data: [] })).toBeNull();
|
||||
expect(parseOpenRouterGenerationTelemetry({ data: { latency: -1, total_cost: "invalid" } })).toBeNull();
|
||||
});
|
||||
|
||||
test("does not count additional successful provider responses as fallbacks", () => {
|
||||
expect(
|
||||
parseOpenRouterGenerationTelemetry({
|
||||
id: "gen-success",
|
||||
provider_responses: [
|
||||
{ status: 200, latency: 100 },
|
||||
{ status: 200, latency: 120 },
|
||||
],
|
||||
}),
|
||||
).toMatchObject({ fallbackCount: 0 });
|
||||
});
|
||||
|
||||
test("caches completed generation records", async () => {
|
||||
const mockedFetch = vi.mocked(fetchWithTrustedCertificatesAsync);
|
||||
mockedFetch.mockResolvedValue({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({ data: { id: "gen-cached", native_tokens_completion: 4 } }),
|
||||
} as Awaited<ReturnType<typeof fetchWithTrustedCertificatesAsync>>);
|
||||
const input = {
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
generationId: "gen-cached",
|
||||
headers: { Authorization: "Bearer test" },
|
||||
};
|
||||
|
||||
await expect(fetchOpenRouterGenerationTelemetryAsync(input)).resolves.toMatchObject({
|
||||
generationId: "gen-cached",
|
||||
outputTokens: 4,
|
||||
});
|
||||
await expect(fetchOpenRouterGenerationTelemetryAsync(input)).resolves.toMatchObject({
|
||||
generationId: "gen-cached",
|
||||
});
|
||||
expect(mockedFetch).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user