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:
@@ -52,6 +52,9 @@ const configSchema = z.object({
|
||||
GEMINI_TIMEOUT_MS: z.coerce.number().int().default(60_000),
|
||||
GEMINI_DAILY_BUDGET_USD: z.coerce.number().default(0),
|
||||
|
||||
/** Strong, rotated ops token for /ops/v1/summary. Set via SSM in production. */
|
||||
OPS_TOKEN: z.string().min(1).default("dev-ops-token-change-me"),
|
||||
|
||||
APP_STORE_MODE: z.enum(["production", "sandbox"]).default("sandbox"),
|
||||
EMAIL_MODE: z.enum(["log", "smtp"]).default("log"),
|
||||
SMTP_HOST: z.string().default(""),
|
||||
@@ -98,6 +101,12 @@ export function loadConfig(env: NodeJS.ProcessEnv = process.env): AppConfig {
|
||||
console.error("SÄKERHETSSTOPP: AAMOS_MODE=gemini kräver GEMINI_API_KEY i produktion.");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!cfg.OPS_TOKEN || cfg.OPS_TOKEN.length < 32 || cfg.OPS_TOKEN.startsWith("dev-ops-token")) {
|
||||
console.error(
|
||||
"SÄKERHETSSTOPP: OPS_TOKEN måste vara en stark, icke-default hemlighet i produktion.",
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user