fix(alerts): проверять ответы и подтверждать сохранённые параметры

This commit is contained in:
Denozordec committed 2026-10-03 17:00:53 +07:00
1 parent 596fea4814
commit 0bcac655ea
6 files changed
+114 -2

No files matched your search

+25
View File
@@ -82,3 +82,28 @@ export type PutRulesBody = z.infer<typeof putRulesSchema>
export type PutTelegramBody = z.infer<typeof putTelegramSchema>
export type RulePreviewTelegram = z.infer<typeof rulePreviewTelegramSchema>
export type TestTelegramBody = z.infer<typeof testTelegramSchema>
// Public response schemas: configured credentials do not prove Telegram connectivity/delivery.
const alertTimestampSchema = z.string().min(1).refine(value => Number.isFinite(Date.parse(value)), "Некорректное время оповещения")
export const telegramPublicSchema = z.object({
chatId:z.string(),tokenConfigured:z.boolean(),connected:z.boolean(),messageThreadId:z.number().int().positive().nullable(),
}).strict().refine(value => value.connected === (value.tokenConfigured && Boolean(value.chatId.trim())), "Противоречивое состояние параметров Telegram")
export const alertRuleResponseSchema = z.object({
id:z.string().min(1),name:z.string().min(1),type:alertTypeSchema,target:z.string(),targets:z.array(z.string().min(1)),groupId:z.string().nullable(),condition:z.string(),conditions:z.array(z.string().min(1)),severity:alertSeveritySchema,enabled:z.boolean(),cooldown:alertCooldownSchema,
confirmStabilitySec:z.number().int().min(0).max(86400).nullable(),recoveryMode:recoveryModeSchema,recoveryStabilitySec:z.number().int().min(0).max(86400).nullable(),chatId:z.string(),lastFiredAt:alertTimestampSchema.nullable(),
}).strict()
export const alertHistoryResponseSchema = z.object({id:z.string().min(1),ruleName:z.string(),severity:alertSeveritySchema,message:z.string(),sent:z.boolean(),firedAt:alertTimestampSchema,source:z.enum(["db","live"])}).strict()
export const alertsMetaResponseSchema = z.object({
servers:z.array(z.string()),greClients:z.array(z.string()),probeTargets:z.array(z.string()),rttLossTargets:z.array(z.string()),trafficServers:z.array(z.string()),
serversDetail:z.array(z.object({name:z.string(),host:z.string(),site:z.string(),country:z.string(),type:z.string()}).strict()),
}).strict()
const alertsConfigResponseShape = {groups:z.array(alertGroupSchema.strict()),rules:z.array(alertRuleResponseSchema)}
function validConfig(value:{groups:{id:string}[];rules:{id:string;groupId:string|null}[]}):boolean {
const groups=new Set(value.groups.map(row=>row.id)),rules=new Set(value.rules.map(row=>row.id))
return groups.size===value.groups.length&&rules.size===value.rules.length&&value.rules.every(row=>row.groupId===null||groups.has(row.groupId))
}
export const alertsResponseSchema = z.object({telegram:telegramPublicSchema,...alertsConfigResponseShape,history:z.array(alertHistoryResponseSchema),meta:alertsMetaResponseSchema}).strict().refine(validConfig,"Повторяющиеся ID или неизвестная группа правила")
export const alertsRulesReceiptSchema = z.object({ok:z.literal(true),...alertsConfigResponseShape}).strict().refine(validConfig,"Повторяющиеся ID или неизвестная группа правила")
export const telegramSettingsReceiptSchema = z.object({ok:z.literal(true),telegram:telegramPublicSchema}).strict()
export const telegramTestReceiptSchema = z.object({ok:z.literal(true)}).strict()
export type AlertsResponse = z.output<typeof alertsResponseSchema>