8f20b2ef1b
- Nya toppnivåblock i /ops/v1/summary: ai_scan, aktivering, engagemang, betalning, jobb, sakerhet. Alla värden läses från DB/cache; null där data saknas, inga påhittade värden. - AI-kostnad i USD mikrocent (native); intäkter fortsatt SEK-öre. - product_analytics_events är källa för volym, latens, lyckandegrad, felfrekvens, aktivering, retention och engagemang. - Nya händelser: scan_started (API) och scan_failed/scan_completed med latencyMs + felkod (worker). latencyMs flödar nu in i scan_completed. - Safety canary-jobb varje timme: re-härleder allergener för alla recept, räknar överifierade publika recept och food-safety-lint; skriver EN rad till ops_safety_canary. Endpointen läser endast sista raden. - Cache-refresh-jobb var 60 s skriver hela summariet till Redis; endpointen serverar cachen med 503 vid cache-miss. - Bearer-token-skydd med OPS_TOKEN; HTTPS-tvång i produktion; ingen PII. - Tester för endpoint, auth, cache-miss och safety canary.
36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
import "./setup-env.js";
|
|
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
import { createDatabase, schema } from "@app/database";
|
|
import { processSafetyCanary } from "../src/processors/safety-canary.js";
|
|
import type { WorkerContext } from "../src/context.js";
|
|
|
|
const testDb = createDatabase(process.env.TEST_DATABASE_URL!);
|
|
const ctx: WorkerContext = { db: testDb.db } as never;
|
|
|
|
describe("RUN_SAFETY_CANARY", () => {
|
|
beforeAll(async () => {
|
|
await testDb.db.delete(schema.opsSafetyCanary);
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await testDb.db.delete(schema.opsSafetyCanary);
|
|
await testDb.pool.end();
|
|
});
|
|
|
|
it("re-härleder allergener och skriver en canary-rad", async () => {
|
|
const result = await processSafetyCanary(ctx);
|
|
|
|
expect(typeof result.allergenInvariantBrott).toBe("number");
|
|
expect(typeof result.overifieradeVisade).toBe("number");
|
|
expect(result.allergenInvariantBrott).toBeGreaterThanOrEqual(0);
|
|
|
|
const latest = await testDb.db
|
|
.select()
|
|
.from(schema.opsSafetyCanary)
|
|
.orderBy(schema.opsSafetyCanary.occurredAt)
|
|
.limit(1);
|
|
expect(latest.length).toBe(1);
|
|
expect(latest[0]!.allergenInvariantBrott).toBe(result.allergenInvariantBrott);
|
|
});
|
|
});
|