- jose v6 не экспортирует KeyLike → CryptoKey - SimpleWebAuthn v13 требует Uint8Array<ArrayBuffer> - targetType 'credential' в AUDIT_TARGET_TYPES (писался в аудит passkey-ов) - target-app: начальные значения host/path/search никогда не читались
137 lines
4.2 KiB
TypeScript
137 lines
4.2 KiB
TypeScript
import { z } from 'zod'
|
|
|
|
export const AUDIT_SEVERITIES = ['info', 'warning', 'critical'] as const
|
|
export type AuditSeverity = (typeof AUDIT_SEVERITIES)[number]
|
|
export const auditSeveritySchema = z.enum(AUDIT_SEVERITIES)
|
|
|
|
export const AUDIT_SOURCE_APPS = [
|
|
'portal',
|
|
'vps',
|
|
'cfdm',
|
|
'bgp',
|
|
'fw',
|
|
'dns',
|
|
'cdn',
|
|
'mm',
|
|
] as const
|
|
export type AuditSourceApp = (typeof AUDIT_SOURCE_APPS)[number]
|
|
export const auditSourceAppSchema = z.enum(AUDIT_SOURCE_APPS)
|
|
|
|
export const AUDIT_TARGET_TYPES = [
|
|
'user',
|
|
'settings',
|
|
'session',
|
|
'system',
|
|
'app_resource',
|
|
'credential',
|
|
] as const
|
|
export type AuditTargetType = (typeof AUDIT_TARGET_TYPES)[number]
|
|
export const auditTargetTypeSchema = z.enum(AUDIT_TARGET_TYPES)
|
|
|
|
/** Well-known portal-native action keys. */
|
|
export const AUDIT_ACTIONS = [
|
|
'auth.login',
|
|
'auth.login_failed',
|
|
'auth.logout',
|
|
'auth.sso_handoff',
|
|
'user.create',
|
|
'user.update',
|
|
'user.delete',
|
|
'user.access_update',
|
|
'app_switcher.update',
|
|
'audit.settings_update',
|
|
'audit.purge',
|
|
] as const
|
|
export type AuditAction = (typeof AUDIT_ACTIONS)[number]
|
|
export const auditActionSchema = z.enum(AUDIT_ACTIONS)
|
|
|
|
export const AUDIT_KINDS = ['logins', 'changes'] as const
|
|
export type AuditKind = (typeof AUDIT_KINDS)[number]
|
|
export const auditKindSchema = z.enum(AUDIT_KINDS)
|
|
|
|
export const AUTH_AUDIT_ACTIONS = [
|
|
'auth.login',
|
|
'auth.login_failed',
|
|
'auth.logout',
|
|
'auth.sso_handoff',
|
|
] as const
|
|
|
|
export const auditLogEntrySchema = z.object({
|
|
id: z.string(),
|
|
event_id: z.string().nullable(),
|
|
source_app: auditSourceAppSchema,
|
|
action: z.string(),
|
|
severity: auditSeveritySchema,
|
|
actor_user_id: z.string().nullable(),
|
|
actor_email: z.string().nullable(),
|
|
actor_name: z.string().nullable(),
|
|
target_type: auditTargetTypeSchema.nullable(),
|
|
target_id: z.string().nullable(),
|
|
summary: z.string(),
|
|
details: z.record(z.string(), z.unknown()).nullable(),
|
|
ip: z.string().nullable(),
|
|
created_at: z.string(),
|
|
})
|
|
export type AuditLogEntry = z.infer<typeof auditLogEntrySchema>
|
|
|
|
export const auditListQuerySchema = z.object({
|
|
action: z.string().optional(),
|
|
severity: auditSeveritySchema.optional(),
|
|
user_id: z.string().optional(),
|
|
actor_email: z.string().email().optional(),
|
|
source_app: auditSourceAppSchema.optional(),
|
|
kind: auditKindSchema.optional(),
|
|
limit: z.coerce.number().int().min(1).max(500).default(200),
|
|
})
|
|
export type AuditListQuery = z.infer<typeof auditListQuerySchema>
|
|
|
|
export const DEFAULT_AUDIT_RETENTION_DAYS = 90
|
|
export const MIN_AUDIT_RETENTION_DAYS = 7
|
|
export const MAX_AUDIT_RETENTION_DAYS = 3650
|
|
|
|
export const auditSettingsSchema = z.object({
|
|
retention_days: z
|
|
.number()
|
|
.int()
|
|
.min(MIN_AUDIT_RETENTION_DAYS)
|
|
.max(MAX_AUDIT_RETENTION_DAYS),
|
|
})
|
|
export type AuditSettings = z.infer<typeof auditSettingsSchema>
|
|
|
|
export const putAuditSettingsSchema = auditSettingsSchema
|
|
export type PutAuditSettings = z.infer<typeof putAuditSettingsSchema>
|
|
|
|
export const auditPurgeResponseSchema = z.object({
|
|
deleted: z.number().int().nonnegative(),
|
|
retention_days: z.number().int(),
|
|
})
|
|
export type AuditPurgeResponse = z.infer<typeof auditPurgeResponseSchema>
|
|
|
|
export const ingestAuditEventSchema = z.object({
|
|
event_id: z.string().min(1).max(128),
|
|
source_app: z.enum(['vps', 'cfdm', 'bgp', 'fw', 'dns', 'cdn', 'mm']),
|
|
action: z.string().min(1).max(200),
|
|
severity: auditSeveritySchema.optional(),
|
|
actor_user_id: z.string().nullable().optional(),
|
|
actor_email: z.string().email().nullable().optional(),
|
|
actor_name: z.string().nullable().optional(),
|
|
target_type: auditTargetTypeSchema.nullable().optional(),
|
|
target_id: z.string().nullable().optional(),
|
|
summary: z.string().min(1).max(500),
|
|
details: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
ip: z.string().nullable().optional(),
|
|
created_at: z.string().optional(),
|
|
})
|
|
export type IngestAuditEvent = z.infer<typeof ingestAuditEventSchema>
|
|
|
|
export const ingestAuditRequestSchema = z.object({
|
|
events: z.array(ingestAuditEventSchema).min(1).max(50),
|
|
})
|
|
export type IngestAuditRequest = z.infer<typeof ingestAuditRequestSchema>
|
|
|
|
export const ingestAuditResponseSchema = z.object({
|
|
accepted: z.number().int().nonnegative(),
|
|
duplicates: z.number().int().nonnegative(),
|
|
})
|
|
export type IngestAuditResponse = z.infer<typeof ingestAuditResponseSchema>
|