feat(ops): /ops/v1/summary med ai/aktivering/engagemang/betalning/jobb/sakerhet + canary
- 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.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import { and, eq, gt, isNull } from "drizzle-orm";
|
||||
import { markMilestone, schema } from "@app/database";
|
||||
import { markMilestone, schema, trackProductAnalytics } from "@app/database";
|
||||
import { scanStarted } from "@app/analytics";
|
||||
import type { JobType, ScanType } from "@app/shared-types";
|
||||
import { confirmScanInputSchema, createScanInputSchema, idParamSchema } from "@app/validation";
|
||||
import { errors, parse } from "../lib/errors.js";
|
||||
@@ -108,6 +109,16 @@ export async function scanRoutes(app: FastifyInstance) {
|
||||
jobType: job.jobType,
|
||||
correlationId: req.correlationId,
|
||||
});
|
||||
|
||||
await trackProductAnalytics(app.db, req.userId, {
|
||||
...scanStarted(),
|
||||
householdId: job.householdId ?? undefined,
|
||||
properties: {
|
||||
scanType: job.scanType,
|
||||
jobType: job.jobType,
|
||||
},
|
||||
});
|
||||
|
||||
return { ok: true, status: "queued" };
|
||||
});
|
||||
|
||||
@@ -353,7 +364,8 @@ function extractProposals(job: { result: unknown }): ProposalItem[] {
|
||||
unit: it.unit ?? null,
|
||||
bestBeforeDate: it.bestBeforeDate ?? null,
|
||||
confidence: typeof it.confidence === "number" ? it.confidence : null,
|
||||
requiresConfirmation: typeof it.requiresConfirmation === "boolean" ? it.requiresConfirmation : null,
|
||||
requiresConfirmation:
|
||||
typeof it.requiresConfirmation === "boolean" ? it.requiresConfirmation : null,
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user